diff --git a/.github/workflows/basket-api-deploy.yml b/.github/workflows/basket-api-deploy.yml new file mode 100644 index 000000000..38c16ed2e --- /dev/null +++ b/.github/workflows/basket-api-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy basket-api + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["basket-api"] + branches: [dev] + types: [completed] + +env: + CHART: basket-api + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/basket-api.yml b/.github/workflows/basket-api.yml index 9d2685382..d8b19993b 100644 --- a/.github/workflows/basket-api.yml +++ b/.github/workflows/basket-api.yml @@ -1,6 +1,7 @@ name: basket-api on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/catalog-api-deploy.yml b/.github/workflows/catalog-api-deploy.yml new file mode 100644 index 000000000..804469296 --- /dev/null +++ b/.github/workflows/catalog-api-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy catalog-api + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["catalog-api"] + branches: [dev] + types: [completed] + +env: + CHART: catalog-api + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/catalog-api.yml b/.github/workflows/catalog-api.yml index ca05a56ea..e3e8e9afe 100644 --- a/.github/workflows/catalog-api.yml +++ b/.github/workflows/catalog-api.yml @@ -1,6 +1,7 @@ name: catalog-api on: + workflow_dispatch: push: branches: - dev @@ -21,6 +22,9 @@ on: env: SERVICE: catalog-api IMAGE: catalog.api + DOTNET_VERSION: 6.0.x + PROJECT_PATH: Services/Catalog/Catalog.API + TESTS_PATH: Services/Catalog/Catalog.UnitTests jobs: @@ -28,65 +32,27 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-test + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + dotnet_version: ${{ env.DOTNET_VERSION }} + project_path: ${{ env.PROJECT_PATH }} + tests_path: ${{ env.TESTS_PATH }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/composite/build-push/action.yml b/.github/workflows/composite/build-push/action.yml new file mode 100644 index 000000000..80be3b857 --- /dev/null +++ b/.github/workflows/composite/build-push/action.yml @@ -0,0 +1,71 @@ +name: "Build and push image" +description: "Builds and pushes an image to a registry" + +inputs: + service: + description: "Service to build" + required: true + registry_host: + description: "Image registry host e.g. myacr.azureacr.io" + required: true + registry_endpoint: + description: "Image registry repo e.g. myacr.azureacr.io/eshop" + required: true + image_name: + description: "Name of image" + required: true + registry_username: + description: "Registry username" + required: true + registry_password: + description: "Registry password" + required: true + +runs: + using: "composite" + steps: + - name: Enable experimental features for the Docker daemon and CLI + shell: bash + run: | + echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json + mkdir -p ~/.docker + echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json + sudo service docker restart + docker version -f '{{.Client.Experimental}}' + docker version -f '{{.Server.Experimental}}' + + - name: Login to Container Registry + uses: docker/login-action@v1 + with: + registry: ${{ inputs.registry_host }} + username: ${{ inputs.registry_username }} + password: ${{ inputs.registry_password }} + + - name: Set branch name as env variable + run: | + currentbranch=$(echo ${GITHUB_REF##*/}) + echo "running on $currentbranch" + echo "BRANCH=$currentbranch" >> $GITHUB_ENV + shell: bash + + - name: Compose build ${{ inputs.service }} + shell: bash + run: sudo -E docker-compose build ${{ inputs.service }} + working-directory: ./src + env: + TAG: ${{ env.BRANCH }} + REGISTRY: ${{ inputs.registry_endpoint }} + + - name: Compose push ${{ inputs.service }} + shell: bash + run: sudo -E docker-compose push ${{ inputs.service }} + working-directory: ./src + env: + TAG: ${{ env.BRANCH }} + REGISTRY: ${{ inputs.registry_endpoint }} + + - name: Create multiarch manifest + shell: bash + run: | + docker --config ~/.docker manifest create ${{ inputs.registry_endpoint }}/${{ inputs.image_name }}:${{ env.BRANCH }} ${{ inputs.registry_endpoint }}/${{ inputs.image_name }}:linux-${{ env.BRANCH }} + docker --config ~/.docker manifest push ${{ inputs.registry_endpoint }}/${{ inputs.image_name }}:${{ env.BRANCH }} \ No newline at end of file diff --git a/.github/workflows/composite/build-test/action.yml b/.github/workflows/composite/build-test/action.yml new file mode 100644 index 000000000..cbee85d73 --- /dev/null +++ b/.github/workflows/composite/build-test/action.yml @@ -0,0 +1,47 @@ +name: "Build for PRe" +description: "Builds a docker image without pushing" + +inputs: + service: + description: "Service to build" + required: true + registry_endpoint: + description: "Image registry repo e.g. myacr.azureacr.io/eshop" + required: true + dotnet_version: + description: "Version of dotnet to use for testing" + required: true + project_path: + description: "Path to project to test e.g. Services/Catalog/Catalog.API" + required: true + tests_path: + description: "Path to test project e.g. Services/Catalog/Catalog.UnitTests" + required: true + +runs: + using: "composite" + steps: + - name: Setup dotnet + uses: actions/setup-dotnet@v1 + with: + dotnet-version: ${{ inputs.dotnet_version }} + + - name: Build and run unit tests + shell: bash + run: | + cd src + dotnet restore "eShopOnContainers-ServicesAndWebApps.sln" + cd ${{ inputs.project_path }} + dotnet build --no-restore + cd - + cd ${{ inputs.tests_path }} + dotnet build --no-restore + dotnet test --no-build -v=normal + + - name: Compose build ${{ inputs.service }} + shell: bash + run: sudo -E docker-compose build ${{ inputs.service }} + working-directory: ./src + env: + TAG: ${{ env.BRANCH }} + REGISTRY: ${{ inputs.registry_endpoint }} diff --git a/.github/workflows/composite/build/action.yml b/.github/workflows/composite/build/action.yml new file mode 100644 index 000000000..b6f7149c4 --- /dev/null +++ b/.github/workflows/composite/build/action.yml @@ -0,0 +1,21 @@ +name: "Build for PRe" +description: "Builds a docker image without pushing" + +inputs: + service: + description: "Service to build" + required: true + registry_endpoint: + description: "Image registry repo e.g. myacr.azureacr.io/eshop" + required: true + +runs: + using: "composite" + steps: + - name: Compose build ${{ inputs.service }} + shell: bash + run: sudo -E docker-compose build ${{ inputs.service }} + working-directory: ./src + env: + TAG: ${{ env.BRANCH }} + REGISTRY: ${{ inputs.registry_endpoint }} diff --git a/.github/workflows/composite/deploy-helm/action.yml b/.github/workflows/composite/deploy-helm/action.yml new file mode 100644 index 000000000..5bcb4ea16 --- /dev/null +++ b/.github/workflows/composite/deploy-helm/action.yml @@ -0,0 +1,54 @@ +name: "Deploy Helm to AKS" +description: "Deploys a helm chart to AKS" + +inputs: + azure_credentials: + description: "Credentials to connect to AKS" + required: true + cluster_name: + description: "Name of AKS cluster" + required: true + resource_group: + description: "Resource group of AKS cluster" + required: true + registry_host: + description: "Image registry host e.g. myacr.azureacr.io" + required: true + chart: + description: "Chart name" + required: true + chart_root: + description: "Root folder of chart" + required: true + namespace: + description: "Namespace to deploy to" + required: true + +runs: + using: "composite" + steps: + - uses: azure/login@v1 + with: + creds: ${{ inputs.azure_credentials }} + + - uses: azure/aks-set-context@v1 + name: Set AKS context + with: + creds: '${{ inputs.azure_credentials }}' + cluster-name: ${{ inputs.cluster_name }} + resource-group: ${{ inputs.resource_group }} + + - name: Set branch name as env variable + shell: bash + run: | + currentbranch=$(echo ${GITHUB_REF##*/}) + echo "running on $currentbranch" + echo "BRANCH=$currentbranch" >> $GITHUB_ENV + + - name: Deploy Chart + shell: bash + run: | + ./deploy-chart.sh -c ${{ inputs.chart }} --dns aks --aks-name ${{ inputs.clusteR_name }} --aks-rg ${{ inputs.resource_group }} -r ${{ inputs.registry_host }} -t $TAG --namespace ${{ inputs.namespace }} --acr-connected + env: + TAG: ${{ env.BRANCH }} + working-directory: ${{ inputs.chart_root }} \ No newline at end of file diff --git a/.github/workflows/identity-api-deploy.yml b/.github/workflows/identity-api-deploy.yml new file mode 100644 index 000000000..c2c0df936 --- /dev/null +++ b/.github/workflows/identity-api-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy identity-api + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["identity-api"] + branches: [dev] + types: [completed] + +env: + CHART: identity-api + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/identity-api.yml b/.github/workflows/identity-api.yml index b57c8151b..71dc79948 100644 --- a/.github/workflows/identity-api.yml +++ b/.github/workflows/identity-api.yml @@ -1,6 +1,7 @@ name: identity-api on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/mobileshoppingagg-deploy.yml b/.github/workflows/mobileshoppingagg-deploy.yml new file mode 100644 index 000000000..bfe6fa967 --- /dev/null +++ b/.github/workflows/mobileshoppingagg-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy mobileshoppingagg + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["mobileshoppingagg"] + branches: [dev] + types: [completed] + +env: + CHART: mobileshoppingagg + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/mobileshoppingagg.yml b/.github/workflows/mobileshoppingagg.yml index 2de0c0370..f05e5e299 100644 --- a/.github/workflows/mobileshoppingagg.yml +++ b/.github/workflows/mobileshoppingagg.yml @@ -1,6 +1,7 @@ name: mobileshoppingagg on: + workflow_dispatch: push: branches: - dev @@ -26,65 +27,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/ordering-api-deploy.yml b/.github/workflows/ordering-api-deploy.yml new file mode 100644 index 000000000..e689d06a4 --- /dev/null +++ b/.github/workflows/ordering-api-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy ordering-api + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["ordering-api"] + branches: [dev] + types: [completed] + +env: + CHART: ordering-api + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/ordering-api.yml b/.github/workflows/ordering-api.yml index 5adec0760..7f6c3fff5 100644 --- a/.github/workflows/ordering-api.yml +++ b/.github/workflows/ordering-api.yml @@ -1,6 +1,7 @@ name: ordering-api on: + workflow_dispatch: push: branches: - dev @@ -21,6 +22,9 @@ on: env: SERVICE: ordering-api IMAGE: ordering.api + DOTNET_VERSION: 6.0.x + PROJECT_PATH: Services/Ordering/Ordering.API + TESTS_PATH: Services/Ordering/Ordering.UnitTests jobs: @@ -28,65 +32,27 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-test + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + dotnet_version: ${{ env.DOTNET_VERSION }} + project_path: ${{ env.PROJECT_PATH }} + tests_path: ${{ env.TESTS_PATH }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/ordering-backgroundtasks-deploy.yml b/.github/workflows/ordering-backgroundtasks-deploy.yml new file mode 100644 index 000000000..1b3b7245e --- /dev/null +++ b/.github/workflows/ordering-backgroundtasks-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy ordering-backgroundtasks + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["ordering-backgroundtasks"] + branches: [dev] + types: [completed] + +env: + CHART: ordering-backgroundtasks + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/ordering-backgroundtasks.yml b/.github/workflows/ordering-backgroundtasks.yml index f8f7badfa..0f5a535d8 100644 --- a/.github/workflows/ordering-backgroundtasks.yml +++ b/.github/workflows/ordering-backgroundtasks.yml @@ -1,6 +1,7 @@ name: ordering-backgroundtasks on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/ordering-signalrhub-deploy.yml b/.github/workflows/ordering-signalrhub-deploy.yml new file mode 100644 index 000000000..455cf7f1d --- /dev/null +++ b/.github/workflows/ordering-signalrhub-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy ordering-signalrhub + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["ordering-signalrhub"] + branches: [dev] + types: [completed] + +env: + CHART: ordering-signalrhub + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/ordering-signalrhub.yml b/.github/workflows/ordering-signalrhub.yml index 564a81458..37d910e53 100644 --- a/.github/workflows/ordering-signalrhub.yml +++ b/.github/workflows/ordering-signalrhub.yml @@ -1,6 +1,7 @@ name: ordering-signalrhub on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/payment-api-deploy.yml b/.github/workflows/payment-api-deploy.yml new file mode 100644 index 000000000..2f37988ed --- /dev/null +++ b/.github/workflows/payment-api-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy payment-api + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["payment-api"] + branches: [dev] + types: [completed] + +env: + CHART: payment-api + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/payment-api.yml b/.github/workflows/payment-api.yml index 3cd18756f..66c941152 100644 --- a/.github/workflows/payment-api.yml +++ b/.github/workflows/payment-api.yml @@ -1,6 +1,7 @@ name: payment-api on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/webhooks-api-deploy.yml b/.github/workflows/webhooks-api-deploy.yml new file mode 100644 index 000000000..4d74a38e6 --- /dev/null +++ b/.github/workflows/webhooks-api-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy webhooks-api + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["webhooks-api"] + branches: [dev] + types: [completed] + +env: + CHART: webhooks-api + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/webhooks-api.yml b/.github/workflows/webhooks-api.yml index f39599d40..bee7b76b3 100644 --- a/.github/workflows/webhooks-api.yml +++ b/.github/workflows/webhooks-api.yml @@ -1,6 +1,7 @@ name: webhooks-api on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/webhooks-client.yml b/.github/workflows/webhooks-client.yml index 6851921fe..1c49a8a5d 100644 --- a/.github/workflows/webhooks-client.yml +++ b/.github/workflows/webhooks-client.yml @@ -1,6 +1,7 @@ name: webhooks-client on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/webmvc-deploy.yml b/.github/workflows/webmvc-deploy.yml new file mode 100644 index 000000000..e70cefed2 --- /dev/null +++ b/.github/workflows/webmvc-deploy.yml @@ -0,0 +1,39 @@ +name: Deploy webmvc + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["webmvc"] + branches: [dev] + types: [completed] + +env: + CHART: webmvc + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/webmvc.yml b/.github/workflows/webmvc.yml index 9fc0cdf86..66fcf06bc 100644 --- a/.github/workflows/webmvc.yml +++ b/.github/workflows/webmvc.yml @@ -1,6 +1,7 @@ name: webmvc on: + workflow_dispatch: push: branches: - dev @@ -29,65 +30,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/webshoppingagg-deploy.yml b/.github/workflows/webshoppingagg-deploy.yml new file mode 100644 index 000000000..2b4bcaf12 --- /dev/null +++ b/.github/workflows/webshoppingagg-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy webshoppingagg + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["webshoppingagg"] + branches: [dev] + types: [completed] + +env: + CHART: webshoppingagg + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/webshoppingagg.yml b/.github/workflows/webshoppingagg.yml index 6c6df5dbb..93bc05e09 100644 --- a/.github/workflows/webshoppingagg.yml +++ b/.github/workflows/webshoppingagg.yml @@ -1,6 +1,7 @@ name: webshoppingagg on: + workflow_dispatch: push: branches: - dev @@ -26,65 +27,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/webspa-deploy.yml b/.github/workflows/webspa-deploy.yml new file mode 100644 index 000000000..2851f6962 --- /dev/null +++ b/.github/workflows/webspa-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy webspa + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["webspa"] + branches: [dev] + types: [completed] + +env: + CHART: webspa + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/webspa.yml b/.github/workflows/webspa.yml index 3dbc3c496..769a6bdcf 100644 --- a/.github/workflows/webspa.yml +++ b/.github/workflows/webspa.yml @@ -1,6 +1,7 @@ name: webspa on: + workflow_dispatch: push: branches: - dev @@ -28,65 +29,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/webstatus-deploy.yml b/.github/workflows/webstatus-deploy.yml new file mode 100644 index 000000000..866a46a5f --- /dev/null +++ b/.github/workflows/webstatus-deploy.yml @@ -0,0 +1,35 @@ +name: Deploy webstatus + +on: + workflow_dispatch: + repository_dispatch: + types: + - deploy + workflow_run: + workflows: ["webstatus"] + branches: [dev] + types: [completed] + +env: + CHART: webstatus + NAMESPACE: eshop + CHART_ROOT: deploy/k8s/helm + +jobs: + deploy-to-k8s: + #if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch' || github.event.workflow_run.conclusion == 'success' }} + if: false + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: ./.github/workflows/composite/deploy-helm + with: + azure_credentials: ${{ secrets.AZURE_CREDENTIALS }} + cluster_name: ${{ secrets.CLUSTER_NAME }} + resource_group: ${{ secrets.RESOURCE_GROUP }} + registry_host: ${{ secrets.REGISTRY_HOST }} + chart: ${{ env.CHART }} + chart_root: ${{ env.CHART_ROOT }} + namespace: ${{ env.NAMESPACE }} diff --git a/.github/workflows/webstatus.yml b/.github/workflows/webstatus.yml index 05d941cf2..0cbb89c6a 100644 --- a/.github/workflows/webstatus.yml +++ b/.github/workflows/webstatus.yml @@ -1,6 +1,7 @@ name: webstatus on: + workflow_dispatch: push: branches: - dev @@ -29,65 +30,24 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build + with: + service: ${{ env.SERVICE }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} BuildLinux: runs-on: ubuntu-latest if: ${{ github.event_name != 'pull_request' }} steps: - - name: 'Checkout Github Action' - uses: actions/checkout@master - - - name: Enable experimental features for the Docker daemon and CLI - run: | - echo $'{\n "experimental": true\n}' | sudo tee /etc/docker/daemon.json - mkdir -p ~/.docker - echo $'{\n "experimental": "enabled"\n}' | sudo tee ~/.docker/config.json - sudo service docker restart - docker version -f '{{.Client.Experimental}}' - docker version -f '{{.Server.Experimental}}' - - - name: Login to Container Registry - uses: docker/login-action@v1 + - name: Checkout code + uses: actions/checkout@v2 + - uses: ./.github/workflows/composite/build-push with: - registry: ${{ secrets.REGISTRY_HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - - - name: Set branch name as env variable - run: | - currentbranch=$(echo ${GITHUB_REF##*/}) - echo "running on $currentbranch" - echo "BRANCH=$currentbranch" >> $GITHUB_ENV - shell: bash - - - name: Compose build ${{ env.SERVICE }} - run: sudo -E docker-compose build ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Compose push ${{ env.SERVICE }} - run: sudo -E docker-compose push ${{ env.SERVICE }} - working-directory: ./src - shell: bash - env: - TAG: ${{ env.BRANCH }} - REGISTRY: ${{ secrets.REGISTRY_ENDPOINT }} - - - name: Create multiarch manifest - run: | - docker --config ~/.docker manifest create ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:linux-${{ env.BRANCH }} - docker --config ~/.docker manifest push ${{ secrets.REGISTRY_ENDPOINT }}/${{ env.IMAGE }}:${{ env.BRANCH }} - shell: bash \ No newline at end of file + service: ${{ env.SERVICE }} + registry_host: ${{ secrets.REGISTRY_HOST }} + registry_endpoint: ${{ secrets.REGISTRY_ENDPOINT }} + image_name: ${{ env.IMAGE }} + registry_username: ${{ secrets.USERNAME }} + registry_password: ${{ secrets.PASSWORD }} \ No newline at end of file diff --git a/README.md b/README.md index 2ea2b7982..28c57eb6f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ Sample .NET Core reference application, powered by Microsoft, based on a simplified microservices architecture and Docker containers. -![](img/eshop-webmvc-app-screenshot.png) +## SPA Application (Angular) + +![](img/eshop-spa-app-home.png) ## Build Status (GitHub Actions) @@ -54,25 +56,25 @@ The basic scenario can be run locally using docker-compose, and also deployed to ### Advanced scenario -The Advanced scenario can be run only in a Kubernetes cluster. Currently this scenario is the same as a basic scenario with the following differences: +The Advanced scenario can be run only in a Kubernetes cluster. Currently, this scenario is the same as a basic scenario with the following differences: - [Deploy to AKS with a Service Mesh for resiliency](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Deploy-to-Azure-Kubernetes-Service-(AKS)) -In the future more features will be implemented in the advanced scenario. +In the future, more features will be implemented in the advanced scenario. ## IMPORTANT NOTES! -**You can use either the latest version of Visual Studio or simply Docker CLI and .NET CLI for Windows, Mac and Linux**. +**You can use either the latest version of Visual Studio or simply Docker CLI and .NET CLI for Windows, Mac, and Linux**. -**Note for Pull Requests (PRs)**: We accept pull request from the community. When doing it, please do it onto the **DEV branch** which is the consolidated work-in-progress branch. Do not request it onto **master** branch. +**Note for Pull Requests (PRs)**: We accept pull requests from the community. When doing it, please do it onto the **DEV branch** which is the consolidated work-in-progress branch. Do not request it onto **main** branch. **NEWS / ANNOUNCEMENTS** Do you want to be up-to-date on .NET Architecture guidance and reference apps like eShopOnContainers? --> Subscribe by "WATCHING" this new GitHub repo: https://github.com/dotnet-architecture/News -## Updated for .NET 5 +## Updated for .NET 6 -eShopOnContainers is updated to .NET 5 "wave" of technologies. Not just compilation but also new recommended code in EF Core, ASP.NET Core, and other new related versions with several significant changes. +eShopOnContainers is updated to .NET 6 "wave" of technologies. Not just compilation but also new recommended code in EF Core, ASP.NET Core, and other new related versions with several significant changes. **See more details in the [Release notes](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Release-notes) wiki page**. @@ -84,15 +86,15 @@ eShopOnContainers is updated to .NET 5 "wave" of technologies. Not just compilat ### Architecture overview -This reference application is cross-platform at the server and client side, thanks to .NET 5 services capable of running on Linux or Windows containers depending on your Docker host, and to Xamarin for mobile apps running on Android, iOS or Windows/UWP plus any browser for the client web apps. -The architecture proposes a microservice oriented architecture implementation with multiple autonomous microservices (each one owning its own data/db) and implementing different approaches within each microservice (simple CRUD vs. DDD/CQRS patterns) using Http as the communication protocol between the client apps and the microservices and supports asynchronous communication for data updates propagation across multiple services based on Integration Events and an Event Bus (a light message broker, to choose between RabbitMQ or Azure Service Bus, underneath) plus other features defined at the [roadmap](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Roadmap). +This reference application is cross-platform at the server and client-side, thanks to .NET 6 services capable of running on Linux or Windows containers depending on your Docker host, and to Xamarin for mobile apps running on Android, iOS, or Windows/UWP plus any browser for the client web apps. +The architecture proposes a microservice oriented architecture implementation with multiple autonomous microservices (each one owning its own data/db) and implementing different approaches within each microservice (simple CRUD vs. DDD/CQRS patterns) using HTTP as the communication protocol between the client apps and the microservices and supports asynchronous communication for data updates propagation across multiple services based on Integration Events and an Event Bus (a light message broker, to choose between RabbitMQ or Azure Service Bus, underneath) plus other features defined at the [roadmap](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Roadmap). ![](img/eshop_logo.png) ![](img/eShopOnContainers-architecture.png) ## Related documentation and guidance -You can find the related reference **Guide/eBook** focusing on **architecting and developing containerized and microservice based .NET Applications** (download link available below) which explains in detail how to develop this kind of architectural style (microservices, Docker containers, Domain-Driven Design for certain microservices) plus other simpler architectural styles, like monolithic apps that can also live as Docker containers. +You can find the related reference **Guide/eBook** focusing on **architecting and developing containerized and microservice-based .NET Applications** (download link available below) which explains in detail how to develop this kind of architectural style (microservices, Docker containers, Domain-Driven Design for certain microservices) plus other simpler architectural styles, like monolithic apps that can also live as Docker containers. There are also additional eBooks focusing on Containers/Docker lifecycle (DevOps, CI/CD, etc.) with Microsoft Tools, already published plus an additional eBook focusing on Enterprise Apps Patterns with Xamarin.Forms. You can download them and start reviewing these Guides/eBooks here: @@ -105,7 +107,7 @@ You can download them and start reviewing these Guides/eBooks here: For more free e-Books check out [.NET Architecture center](https://dot.net/architecture). If you have an e-book feedback, let us know by creating a new issue here: ## Are you new to **microservices** and **cloud-native development**? -Take a look at the free course [Create and deploy a cloud-native ASP.NET Core microservice](https://docs.microsoft.com/en-us/learn/modules/microservices-aspnet-core/) on MS Learn. This module explains microservices concepts, cloud-native technologies, and reduce the friction in getting started with `eShopOnContainers`. +Take a look at the free course [Create and deploy a cloud-native ASP.NET Core microservice](https://docs.microsoft.com/en-us/learn/modules/microservices-aspnet-core/) on MS Learn. This module explains microservices concepts, cloud-native technologies, and reduces the friction in getting started with `eShopOnContainers`. ## Read further diff --git a/branch-guide.md b/branch-guide.md index 040d9bab4..633dc8faf 100644 --- a/branch-guide.md +++ b/branch-guide.md @@ -2,8 +2,11 @@ Following are the most important branches: -- `dev`: Contains the latest code **and it is the branch actively developed**. Note that **all PRs must be against the `dev` branch to be considered**. This branch is developed using `.NET 5` -- `main`: Synced time to time from `dev`.It contains "stable" code, although not the latest one. Right now, this branch contains changes specific to `.NET Core 3.1` +- `dev`: Contains the latest code **and it is the branch actively developed**. Note that **all PRs must be against the `dev` branch to be considered**. This branch is developed using `.NET 6` +- `release/net-5`: Contains the code changes specific to the `.NET 5` +- `release/net-3.1.1`: Contains the code changes specific to the `.NET 3.1` + +> [!DISCLAIMER]: The `main` branch contains the old code base and will get obsolete in the future. So it's recommended to refer to different [tags](https://github.com/dotnet-architecture/eShopOnContainers/tags) to avoid any confusion. Any other branch is considered temporary and could be deleted at any time. Do not submit any PR against them! diff --git a/build/acr-build/queue-all.ps1 b/build/acr-build/queue-all.ps1 index d160abfc1..eca901949 100644 --- a/build/acr-build/queue-all.ps1 +++ b/build/acr-build/queue-all.ps1 @@ -31,5 +31,3 @@ $services |% { Write-Host "Setting ACR build $bname ($bimg)" az acr build-task create --registry $acrName --name $bname --image ${bimg}:$gitBranch --context $gitContext --branch $gitBranch --git-access-token $patToken --file $bfile } - -# Basket.API diff --git a/deploy/azure/az/servicebus/sbusdeploy.json b/deploy/azure/az/servicebus/sbusdeploy.json index 46ac930aa..afd797d64 100644 --- a/deploy/azure/az/servicebus/sbusdeploy.json +++ b/deploy/azure/az/servicebus/sbusdeploy.json @@ -16,6 +16,9 @@ "OrderingSubscriptionName": "Ordering", "GracePeriodSubscriptionName": "GracePeriod", "PaymentSubscriptionName": "Payment", + "BackgroundTaskSubscriptionName": "backgroundtasks", + "OrderingSignalrHubSubscriptionName": "Ordering.signalrhub", + "WebhooksSubscriptionName": "Webhooks", "location": "[resourceGroup().location]", "sbVersion": "2015-08-01", "defaultSASKeyName": "Root", @@ -172,6 +175,66 @@ "autoDeleteOnIdle": "10675199.02:48:05.4775807", "entityAvailabilityStatus": "Available" } + }, + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('BackgroundTaskSubscriptionName')]", + "type": "Subscriptions", + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ], + "properties": { + "lockDuration": "00:00:30", + "requiresSession": false, + "defaultMessageTimeToLive": "14.00:00:00", + "deadLetteringOnMessageExpiration": true, + "deadLetteringOnFilterEvaluationExceptions": true, + "maxDeliveryCount": 10, + "enableBatchedOperations": false, + "status": "Active", + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "entityAvailabilityStatus": "Available" + } + }, + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('OrderingSignalrHubSubscriptionName')]", + "type": "Subscriptions", + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ], + "properties": { + "lockDuration": "00:00:30", + "requiresSession": false, + "defaultMessageTimeToLive": "14.00:00:00", + "deadLetteringOnMessageExpiration": true, + "deadLetteringOnFilterEvaluationExceptions": true, + "maxDeliveryCount": 10, + "enableBatchedOperations": false, + "status": "Active", + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "entityAvailabilityStatus": "Available" + } + }, + { + "apiVersion": "[variables('sbVersion')]", + "name": "[variables('WebhooksSubscriptionName')]", + "type": "Subscriptions", + "dependsOn": [ + "[variables('serviceBusTopicName')]" + ], + "properties": { + "lockDuration": "00:00:30", + "requiresSession": false, + "defaultMessageTimeToLive": "14.00:00:00", + "deadLetteringOnMessageExpiration": true, + "deadLetteringOnFilterEvaluationExceptions": true, + "maxDeliveryCount": 10, + "enableBatchedOperations": false, + "status": "Active", + "autoDeleteOnIdle": "10675199.02:48:05.4775807", + "entityAvailabilityStatus": "Available" + } } ] } diff --git a/deploy/k8s/archived/README.md b/deploy/k8s/archived/README.md deleted file mode 100644 index 3e464c3d1..000000000 --- a/deploy/k8s/archived/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Kubernetes deployment - -This folder contains the files required to deploy eShopOnContainers to a Kubernetes cluster. - -For more information see the following articles in the [wiki](https://github.com/dotnet-architecture/eShopOnContainers/wiki): - -- [Deploy to Local Kubernetes](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Deploy-to-Local-Kubernetes) -- [Deploy to Azure Kubernetes Service (AKS)](https://github.com/dotnet-architecture/eShopOnContainers/wiki/Deploy-to-Azure-Kubernetes-Service-(AKS)) diff --git a/deploy/k8s/archived/create-aks.ps1 b/deploy/k8s/archived/create-aks.ps1 deleted file mode 100644 index 327f5fd6b..000000000 --- a/deploy/k8s/archived/create-aks.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -Param( - [parameter(Mandatory=$true)][string]$resourceGroupName, - [parameter(Mandatory=$true)][string]$location, - [parameter(Mandatory=$true)][string]$serviceName, - [parameter(Mandatory=$true)][string]$dnsNamePrefix, - [parameter(Mandatory=$false)][string]$registryName, - [parameter(Mandatory=$true)][bool]$createAcr=$true, - [parameter(Mandatory=$false)][int]$nodeCount=3, - [parameter(Mandatory=$false)][string]$nodeVMSize="Standard_D2_v2", - [parameter(Mandatory=$false)][bool]$enableHttpApplicationAddon=$true, - [parameter(Mandatory=$false)][bool]$enableAzureMonitoring=$false, - [parameter(Mandatory=$false)][ValidateSet("VirtualMachineScaleSets","AvailabilitySet",IgnoreCase=$true)]$vmSetType="VirtualMachineScaleSets" -) - -# Create resource group -Write-Host "Creating Azure Resource Group..." -ForegroundColor Yellow -az group create --name=$resourceGroupName --location=$location - -if ($createAcr -eq $true) { - # Create Azure Container Registry - if ([string]::IsNullOrEmpty($registryName)) { - $registryName=$serviceName - } - Write-Host "Creating Azure Container Registry named $registryName" -ForegroundColor Yellow - az acr create -n $registryName -g $resourceGroupName -l $location --admin-enabled true --sku Basic -} - -# Create kubernetes cluster in AKS -Write-Host "Creating AKS $resourceGroupName/$serviceName" -ForegroundColor Yellow -az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsNamePrefix --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize --vm-set-type $vmSetType - -if ($enableHttpApplicationAddon) { - Write-Host "Enabling Http Applciation Routing in AKS $serviceName" -ForegroundColor Yellow - az aks enable-addons --resource-group $resourceGroupName --name $serviceName --addons http_application_routing -} - -if ($enableAzureMonitoring) { - Write-Host "Enabling Azure Monitoring in AKS $serviceName" -ForegroundColor Yellow - az aks enable-addons --resource-group $resourceGroupName --name $serviceName --addons monitoring -} - -# Retrieve kubernetes cluster configuration and save it under ~/.kube/config -Write-Host "Getting Kubernetes config..." -ForegroundColor Yellow -az aks get-credentials --resource-group=$resourceGroupName --name=$serviceName - -if ($createAcr -eq $true) { - # Show ACR credentials - Write-Host "ACR $registryName credentials:" -ForegroundColor Yellow - az acr credential show -n $registryName -} diff --git a/deploy/k8s/archived/dashboard-adminuser.yaml b/deploy/k8s/archived/dashboard-adminuser.yaml deleted file mode 100644 index 9f24303cd..000000000 --- a/deploy/k8s/archived/dashboard-adminuser.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: admin-user - namespace: kubernetes-dashboard ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: admin-user -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: -- kind: ServiceAccount - name: admin-user - namespace: kubernetes-dashboard diff --git a/deploy/k8s/archived/enable-tls.ps1 b/deploy/k8s/archived/enable-tls.ps1 deleted file mode 100644 index cd4ef3ffe..000000000 --- a/deploy/k8s/archived/enable-tls.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -Param ( -[parameter(Mandatory=$false)][string]$aksName="", -[parameter(Mandatory=$false)][string]$aksRg="" -) - -if ($aksName -and $aksRg) { - - $aks=$(az aks show -n $aksName -g $aksRg -o json | ConvertFrom-Json) - if (-not $aks) { - Write-Host "AKS $aksName not found in RG $aksRg" -ForegroundColor Red - exit 1 - } - - Write-Host "Switching kubectl context to $aksRg/$aksName" -ForegroundColor Yellow - az aks get-credentials -g $aksRg -n $aksName -} - -Write-Host "Installing cert-manager on current cluster" - -kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.11.0/cert-manager.yaml --validate=false diff --git a/deploy/k8s/archived/helm-rbac.yaml b/deploy/k8s/archived/helm-rbac.yaml deleted file mode 100644 index b6180329a..000000000 --- a/deploy/k8s/archived/helm-rbac.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: tiller - namespace: kube-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: tiller -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: - - kind: ServiceAccount - name: tiller - namespace: kube-system \ No newline at end of file diff --git a/deploy/k8s/archived/helm/aks-httpaddon-cfg.yaml b/deploy/k8s/archived/helm/aks-httpaddon-cfg.yaml deleted file mode 100644 index b9576b0b6..000000000 --- a/deploy/k8s/archived/helm/aks-httpaddon-cfg.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - labels: -# addonmanager.kubernetes.io/mode: Reconcile - app: addon-http-application-routing-ingress-nginx - kubernetes.io/cluster-service: "true" - name: addon-http-application-routing-nginx-configuration - namespace: kube-system -data: - proxy-buffer-size: "128k" - proxy-buffers: "4 256k" diff --git a/deploy/k8s/archived/helm/apigwms/.helmignore b/deploy/k8s/archived/helm/apigwms/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/apigwms/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/apigwms/Chart.yaml b/deploy/k8s/archived/helm/apigwms/Chart.yaml deleted file mode 100644 index 3ad3fdf46..000000000 --- a/deploy/k8s/archived/helm/apigwms/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: apigwms -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/apigwms/envoy.yaml b/deploy/k8s/archived/helm/apigwms/envoy.yaml deleted file mode 100644 index 1ae8c45a1..000000000 --- a/deploy/k8s/archived/helm/apigwms/envoy.yaml +++ /dev/null @@ -1,139 +0,0 @@ -admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 -static_resources: - listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto - stat_prefix: ingress_http - route_config: - name: eshop_backend_route - virtual_hosts: - - name: eshop_backend - domains: - - "*" - routes: - - name: "c-short" - match: - prefix: "/c/" - route: - auto_host_rewrite: true - prefix_rewrite: "/catalog-api/" - cluster: catalog - - name: "c-long" - match: - prefix: "/catalog-api/" - route: - auto_host_rewrite: true - cluster: catalog - - name: "o-short" - match: - prefix: "/o/" - route: - auto_host_rewrite: true - prefix_rewrite: "/ordering-api/" - cluster: ordering - - name: "o-long" - match: - prefix: "/ordering-api/" - route: - auto_host_rewrite: true - cluster: ordering - - name: "h-long" - match: - prefix: "/hub/notificationhub" - route: - auto_host_rewrite: true - cluster: signalr-hub - timeout: 300s - - name: "b-short" - match: - prefix: "/b/" - route: - auto_host_rewrite: true - prefix_rewrite: "/basket-api/" - cluster: basket - - name: "b-long" - match: - prefix: "/basket-api/" - route: - auto_host_rewrite: true - cluster: basket - - name: "agg" - match: - prefix: "/" - route: - auto_host_rewrite: true - prefix_rewrite: "/" - cluster: shoppingagg - http_filters: - - name: envoy.router - access_log: - - name: envoy.file_access_log - filter: - not_health_check_filter: {} - config: - json_format: - time: "%START_TIME%" - protocol: "%PROTOCOL%" - duration: "%DURATION%" - request_method: "%REQ(:METHOD)%" - request_host: "%REQ(HOST)%" - path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" - response_flags: "%RESPONSE_FLAGS%" - route_name: "%ROUTE_NAME%" - upstream_host: "%UPSTREAM_HOST%" - upstream_cluster: "%UPSTREAM_CLUSTER%" - upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%" - path: "/tmp/access.log" - clusters: - - name: shoppingagg - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: webshoppingagg - port_value: 80 - - name: catalog - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: catalog-api - port_value: 80 - - name: basket - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: basket-api - port_value: 80 - - name: ordering - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: ordering-api - port_value: 80 - - name: signalr-hub - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: ordering-signalrhub - port_value: 80 diff --git a/deploy/k8s/archived/helm/apigwms/templates/NOTES.txt b/deploy/k8s/archived/helm/apigwms/templates/NOTES.txt deleted file mode 100644 index 74b3eedda..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop API Gateway for Mobile Shopping services installed --------------------------------------------------------- \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwms/templates/_helpers.tpl b/deploy/k8s/archived/helm/apigwms/templates/_helpers.tpl deleted file mode 100644 index 2ae403c2f..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "apigwms.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "apigwms.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "apigwms.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/apigwms/templates/_names.tpl b/deploy/k8s/archived/helm/apigwms/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwms/templates/deployment.yaml b/deploy/k8s/archived/helm/apigwms/templates/deployment.yaml deleted file mode 100644 index 2c5703103..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/deployment.yaml +++ /dev/null @@ -1,110 +0,0 @@ -{{- $name := include "apigwms.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -{{- $envoycfgname := printf "%s-%s" "envoy" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "apigwms.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "apigwms.name" . }} - chart: {{ template "apigwms.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "apigwms.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "apigwms.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - volumes: - - name: config - configMap: - name: {{ $envoycfgname }} - items: - - key: envoy.yaml - path: envoy.yaml - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: IfNotPresent - volumeMounts: - - name: config - mountPath: {{ .Values.envoy.configPath }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: admin - containerPort: 8001 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/apigwms/templates/envoy-cm.yaml b/deploy/k8s/archived/helm/apigwms/templates/envoy-cm.yaml deleted file mode 100644 index 76da5832b..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/envoy-cm.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- $name := include "apigwms.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "envoy-{{ $name }}" - labels: - app: {{ template "apigwms.name" . }} - chart: {{ template "apigwms.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - {{ (.Files.Glob "envoy.yaml").AsConfig | indent 2 }} - diff --git a/deploy/k8s/archived/helm/apigwms/templates/ingress.yaml b/deploy/k8s/archived/helm/apigwms/templates/ingress.yaml deleted file mode 100644 index bc0c6d05b..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/ingress.yaml +++ /dev/null @@ -1,47 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.mobileshoppingapigw -}} - -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "apigwms.fullname" . }} - labels: - app: {{ template "apigwms.name" . }} - chart: {{ template "apigwms.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/apigwms/templates/service.yaml b/deploy/k8s/archived/helm/apigwms/templates/service.yaml deleted file mode 100644 index aa087d428..000000000 --- a/deploy/k8s/archived/helm/apigwms/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.mobileshoppingapigw }} - labels: - app: {{ template "apigwms.name" . }} - chart: {{ template "apigwms.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.adminPort }} - targetPort: admin - protocol: TCP - name: admin - selector: - app: {{ template "apigwms.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/apigwms/values.yaml b/deploy/k8s/archived/helm/apigwms/values.yaml deleted file mode 100644 index 4a92d85e9..000000000 --- a/deploy/k8s/archived/helm/apigwms/values.yaml +++ /dev/null @@ -1,45 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /mobileshoppingapigw - -image: - repository: envoyproxy/envoy - tag: v1.11.1 - -service: - type: ClusterIP - port: 80 - adminPort: 8001 - -ingress: - enabled: true - annotations: - nginx.ingress.kubernetes.io/rewrite-target: "/" - ingress.kubernetes.io/rewrite-target: "/" - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -env: {} - -envoy: - configPath: /etc/envoy - -probes: - liveness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 15 - port: 8001 - readiness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 60 - port: 8001 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwws/.helmignore b/deploy/k8s/archived/helm/apigwws/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/apigwws/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/apigwws/Chart.yaml b/deploy/k8s/archived/helm/apigwws/Chart.yaml deleted file mode 100644 index 0a6c34e62..000000000 --- a/deploy/k8s/archived/helm/apigwws/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: apigwws -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/apigwws/envoy.yaml b/deploy/k8s/archived/helm/apigwws/envoy.yaml deleted file mode 100644 index 1ae8c45a1..000000000 --- a/deploy/k8s/archived/helm/apigwws/envoy.yaml +++ /dev/null @@ -1,139 +0,0 @@ -admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 -static_resources: - listeners: - - address: - socket_address: - address: 0.0.0.0 - port_value: 80 - filter_chains: - - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto - stat_prefix: ingress_http - route_config: - name: eshop_backend_route - virtual_hosts: - - name: eshop_backend - domains: - - "*" - routes: - - name: "c-short" - match: - prefix: "/c/" - route: - auto_host_rewrite: true - prefix_rewrite: "/catalog-api/" - cluster: catalog - - name: "c-long" - match: - prefix: "/catalog-api/" - route: - auto_host_rewrite: true - cluster: catalog - - name: "o-short" - match: - prefix: "/o/" - route: - auto_host_rewrite: true - prefix_rewrite: "/ordering-api/" - cluster: ordering - - name: "o-long" - match: - prefix: "/ordering-api/" - route: - auto_host_rewrite: true - cluster: ordering - - name: "h-long" - match: - prefix: "/hub/notificationhub" - route: - auto_host_rewrite: true - cluster: signalr-hub - timeout: 300s - - name: "b-short" - match: - prefix: "/b/" - route: - auto_host_rewrite: true - prefix_rewrite: "/basket-api/" - cluster: basket - - name: "b-long" - match: - prefix: "/basket-api/" - route: - auto_host_rewrite: true - cluster: basket - - name: "agg" - match: - prefix: "/" - route: - auto_host_rewrite: true - prefix_rewrite: "/" - cluster: shoppingagg - http_filters: - - name: envoy.router - access_log: - - name: envoy.file_access_log - filter: - not_health_check_filter: {} - config: - json_format: - time: "%START_TIME%" - protocol: "%PROTOCOL%" - duration: "%DURATION%" - request_method: "%REQ(:METHOD)%" - request_host: "%REQ(HOST)%" - path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" - response_flags: "%RESPONSE_FLAGS%" - route_name: "%ROUTE_NAME%" - upstream_host: "%UPSTREAM_HOST%" - upstream_cluster: "%UPSTREAM_CLUSTER%" - upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%" - path: "/tmp/access.log" - clusters: - - name: shoppingagg - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: webshoppingagg - port_value: 80 - - name: catalog - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: catalog-api - port_value: 80 - - name: basket - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: basket-api - port_value: 80 - - name: ordering - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: ordering-api - port_value: 80 - - name: signalr-hub - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: ordering-signalrhub - port_value: 80 diff --git a/deploy/k8s/archived/helm/apigwws/templates/NOTES.txt b/deploy/k8s/archived/helm/apigwws/templates/NOTES.txt deleted file mode 100644 index 8214afb1e..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop API Gateway for Web Shopping services installed ------------------------------------------------------ \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwws/templates/_helpers.tpl b/deploy/k8s/archived/helm/apigwws/templates/_helpers.tpl deleted file mode 100644 index b6aa6b483..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "apigwws.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "apigwws.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "apigwws.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/apigwws/templates/_names.tpl b/deploy/k8s/archived/helm/apigwws/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/apigwws/templates/deployment.yaml b/deploy/k8s/archived/helm/apigwws/templates/deployment.yaml deleted file mode 100644 index 3aedde6dd..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/deployment.yaml +++ /dev/null @@ -1,109 +0,0 @@ -{{- $name := include "apigwws.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -{{- $envoycfgname := printf "%s-%s" "envoy" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "apigwws.fullname" . }} - labels: - app: {{ template "apigwws.name" . }} - chart: {{ template "apigwws.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "apigwws.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "apigwws.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - volumes: - - name: config - configMap: - name: {{ $envoycfgname }} - items: - - key: envoy.yaml - path: envoy.yaml - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - volumeMounts: - - name: config - mountPath: {{ .Values.envoy.configPath }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: admin - containerPort: 8001 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/apigwws/templates/envoy-cm.yaml b/deploy/k8s/archived/helm/apigwws/templates/envoy-cm.yaml deleted file mode 100644 index 6d41bd2e2..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/envoy-cm.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- $name := include "apigwws.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "envoy-{{ $name }}" - labels: - app: {{ template "apigwws.name" . }} - chart: {{ template "apigwws.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - {{ (.Files.Glob "envoy.yaml").AsConfig | indent 2 }} - diff --git a/deploy/k8s/archived/helm/apigwws/templates/ingress.yaml b/deploy/k8s/archived/helm/apigwws/templates/ingress.yaml deleted file mode 100644 index 945038081..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/ingress.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.webshoppingapigw -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "apigwws.fullname" . }} - labels: - app: {{ template "apigwws.name" . }} - chart: {{ template "apigwws.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/apigwws/templates/service.yaml b/deploy/k8s/archived/helm/apigwws/templates/service.yaml deleted file mode 100644 index 55f6daf3f..000000000 --- a/deploy/k8s/archived/helm/apigwws/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.webshoppingapigw }} - labels: - app: {{ template "apigwws.name" . }} - chart: {{ template "apigwws.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.adminPort }} - targetPort: admin - protocol: TCP - name: admin - selector: - app: {{ template "apigwws.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/apigwws/values.yaml b/deploy/k8s/archived/helm/apigwws/values.yaml deleted file mode 100644 index fb1182dac..000000000 --- a/deploy/k8s/archived/helm/apigwws/values.yaml +++ /dev/null @@ -1,46 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webshoppingapigw - -image: - repository: envoyproxy/envoy - tag: v1.11.1 - -service: - type: ClusterIP - port: 80 - adminPort: 8001 - -ingress: - enabled: true - annotations: - nginx.ingress.kubernetes.io/rewrite-target: "/" - ingress.kubernetes.io/rewrite-target: "/" - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: {} - -envoy: - configPath: /etc/envoy - -probes: - liveness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 15 - port: 8001 - readiness: - path: /ready - initialDelaySeconds: 5 - periodSeconds: 60 - port: 8001 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/app.yaml b/deploy/k8s/archived/helm/app.yaml deleted file mode 100644 index acea31ef1..000000000 --- a/deploy/k8s/archived/helm/app.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# This helm values file defines app-based settings -# Charts use those values, so this file **MUST** be included in all chart releases - -app: # app global settings - name: "my-eshop" # Override for custom app name - ingress: # ingress related settings - entries: - basket: basket-api # ingress entry for basket api - catalog: catalog-api # ingress entry for catalog api - ordering: ordering-api # ingress entry for ordering api - identity: identity # ingress entry for identity api - mvc: webmvc # ingress entry for web mvc - spa: "" # ingress entry for web spa - status: webstatus # ingress entry for web status - webshoppingapigw: webshoppingapigw # ingress entry for web shopping Agw - mobileshoppingapigw: mobileshoppingapigw # ingress entry for mobile shopping Agw - webshoppingagg: webshoppingagg # ingress entry for web shopping aggregator - mobileshoppingagg: mobileshoppingagg # ingress entry for mobile shopping aggregator - payment: payment-api # ingress entry for payment api - webhooks: webhooks-api # ingress entry for webhooks api - webhooksweb: webhooks-web # ingress entry for webhooks web demo client - svc: - basket: basket-api # service name for basket api - catalog: catalog-api # service name for catalog api - ordering: ordering-api # service name for ordering api - orderingbackgroundtasks: ordering-backgroundtasks # service name for orderingbackgroundtasks - orderingsignalrhub: ordering-signalrhub # service name for orderingsignalrhub - identity: identity-api # service name for identity api - mvc: webmvc # service name for web mvc - spa: webspa # service name for web spa - status: webstatus # service name for web status - webshoppingapigw: webshoppingapigw # service name for web shopping Agw - mobileshoppingapigw: mobileshoppingapigw # service name for mobile shopping Agw - webshoppingagg: webshoppingagg # service name for web shopping aggregator - mobileshoppingagg: mobileshoppingagg # service name for mobile shopping aggregator - payment: payment-api # service name for payment api - webhooks: webhooks-api # service name for webhooks api - webhooksweb: webhooks-client # service name for webhooks web diff --git a/deploy/k8s/archived/helm/basket-api/.helmignore b/deploy/k8s/archived/helm/basket-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/basket-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/basket-api/Chart.yaml b/deploy/k8s/archived/helm/basket-api/Chart.yaml deleted file mode 100644 index fd3e01486..000000000 --- a/deploy/k8s/archived/helm/basket-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: basket-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/basket-api/templates/NOTES.txt b/deploy/k8s/archived/helm/basket-api/templates/NOTES.txt deleted file mode 100644 index 8ba2c89ee..000000000 --- a/deploy/k8s/archived/helm/basket-api/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Basket API installed. --------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "basket-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/basket-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/basket-api/templates/_helpers.tpl deleted file mode 100644 index 550eb2e6c..000000000 --- a/deploy/k8s/archived/helm/basket-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "basket-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "basket-api.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "basket-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/basket-api/templates/_names.tpl b/deploy/k8s/archived/helm/basket-api/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/basket-api/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/basket-api/templates/configmap.yaml b/deploy/k8s/archived/helm/basket-api/templates/configmap.yaml deleted file mode 100644 index 8a36f74ac..000000000 --- a/deploy/k8s/archived/helm/basket-api/templates/configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- $name := include "basket-api.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "basket-api.name" . }} - chart: {{ template "basket-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - basket__ConnectionString: {{ .Values.inf.redis.basket.constr }} - urls__IdentityUrl: http://{{ .Values.app.svc.identity }} - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/basket-api/templates/deployment.yaml b/deploy/k8s/archived/helm/basket-api/templates/deployment.yaml deleted file mode 100644 index dc90666f5..000000000 --- a/deploy/k8s/archived/helm/basket-api/templates/deployment.yaml +++ /dev/null @@ -1,99 +0,0 @@ -{{- $name := include "basket-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "basket-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "basket-api.name" . }} - chart: {{ template "basket-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "basket-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "basket-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: grpc - containerPort: 81 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/basket-api/templates/service.yaml b/deploy/k8s/archived/helm/basket-api/templates/service.yaml deleted file mode 100644 index 1783c59aa..000000000 --- a/deploy/k8s/archived/helm/basket-api/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.basket }} - labels: - app: {{ template "basket-api.name" . }} - chart: {{ template "basket-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.grpcPort }} - targetPort: grpc - protocol: TCP - name: grpc - selector: - app: {{ template "basket-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/basket-api/values.yaml b/deploy/k8s/archived/helm/basket-api/values.yaml deleted file mode 100644 index dcd6aa763..000000000 --- a/deploy/k8s/archived/helm/basket-api/values.yaml +++ /dev/null @@ -1,61 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /basket-api - -image: - repository: eshop/basket.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - grpcPort: 81 - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ConnectionString - key: basket__ConnectionString - - name: EventBusConnection - key: all__EventBusConnection - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: IdentityUrl - key: urls__IdentityUrl - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: OrchestratorType - value: 'K8S' - - name: PORT - value: "80" - - name: GRPC_PORT - value: "81" -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 - -ingress: - enabled: false \ No newline at end of file diff --git a/deploy/k8s/archived/helm/basket-data/.helmignore b/deploy/k8s/archived/helm/basket-data/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/basket-data/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/basket-data/Chart.yaml b/deploy/k8s/archived/helm/basket-data/Chart.yaml deleted file mode 100644 index 67ceddee1..000000000 --- a/deploy/k8s/archived/helm/basket-data/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: basket-data -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/basket-data/templates/NOTES.txt b/deploy/k8s/archived/helm/basket-data/templates/NOTES.txt deleted file mode 100644 index c10513333..000000000 --- a/deploy/k8s/archived/helm/basket-data/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Redis for keystore data installed ----------------------------------------- - -Redis is not directly exposed outside cluster. If need to access it from outside use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "basket-data.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/basket-data/templates/_helpers.tpl b/deploy/k8s/archived/helm/basket-data/templates/_helpers.tpl deleted file mode 100644 index 74b51b089..000000000 --- a/deploy/k8s/archived/helm/basket-data/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "basket-data.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "basket-data.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "basket-data.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/basket-data/templates/deployment.yaml b/deploy/k8s/archived/helm/basket-data/templates/deployment.yaml deleted file mode 100644 index 8ccceceeb..000000000 --- a/deploy/k8s/archived/helm/basket-data/templates/deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "basket-data.fullname" . }} - labels: - app: {{ template "basket-data.name" . }} - chart: {{ template "basket-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "basket-data.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "basket-data.name" . }} - release: {{ .Release.Name }} - spec: - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 6379 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} diff --git a/deploy/k8s/archived/helm/basket-data/templates/service.yaml b/deploy/k8s/archived/helm/basket-data/templates/service.yaml deleted file mode 100644 index 98b8cc3bd..000000000 --- a/deploy/k8s/archived/helm/basket-data/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.inf.redis.basket.svc }} - labels: - app: {{ template "basket-data.name" . }} - chart: {{ template "basket-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "basket-data.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/basket-data/values.yaml b/deploy/k8s/archived/helm/basket-data/values.yaml deleted file mode 100644 index 17cc75ee7..000000000 --- a/deploy/k8s/archived/helm/basket-data/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -replicaCount: 1 - -image: - repository: redis - tag: 4.0.10 - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 6379 - - -resources: {} - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/deploy/k8s/archived/helm/catalog-api/.helmignore b/deploy/k8s/archived/helm/catalog-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/catalog-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/catalog-api/Chart.yaml b/deploy/k8s/archived/helm/catalog-api/Chart.yaml deleted file mode 100644 index a143a0afe..000000000 --- a/deploy/k8s/archived/helm/catalog-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: catalog-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/catalog-api/templates/NOTES.txt b/deploy/k8s/archived/helm/catalog-api/templates/NOTES.txt deleted file mode 100644 index 1f01a2b92..000000000 --- a/deploy/k8s/archived/helm/catalog-api/templates/NOTES.txt +++ /dev/null @@ -1,9 +0,0 @@ -eShop Catalog API installed. ----------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "catalog-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 - diff --git a/deploy/k8s/archived/helm/catalog-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/catalog-api/templates/_helpers.tpl deleted file mode 100644 index 6fd128e77..000000000 --- a/deploy/k8s/archived/helm/catalog-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "catalog-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "catalog-api.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "catalog-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/catalog-api/templates/_names.tpl b/deploy/k8s/archived/helm/catalog-api/templates/_names.tpl deleted file mode 100644 index 605e92e7e..000000000 --- a/deploy/k8s/archived/helm/catalog-api/templates/_names.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} - -{{- define "protocol" -}} -{{- if .Values.inf.tls.enabled -}} -{{- printf "%s" "https" -}} -{{- else -}} -{{- printf "%s" "http" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/catalog-api/templates/configmap.yaml b/deploy/k8s/archived/helm/catalog-api/templates/configmap.yaml deleted file mode 100644 index 292b9e9b9..000000000 --- a/deploy/k8s/archived/helm/catalog-api/templates/configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- $name := include "catalog-api.fullname" . -}} -{{- $sqlsrv := include "sql-name" . -}} -{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} -{{- $protocol := include "protocol" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "catalog-api.name" . }} - chart: {{ template "catalog-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - catalog__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.catalog.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; - catalog__PicBaseUrl: {{ $protocol }}://{{ $webshoppingapigw }}/c/api/v1/catalog/items/[0]/pic/ - catalog__AzureStorageEnabled: "{{ .Values.inf.misc.useAzureStorage }}" - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/catalog-api/templates/deployment.yaml b/deploy/k8s/archived/helm/catalog-api/templates/deployment.yaml deleted file mode 100644 index 33a0ad5b4..000000000 --- a/deploy/k8s/archived/helm/catalog-api/templates/deployment.yaml +++ /dev/null @@ -1,99 +0,0 @@ -{{- $name := include "catalog-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "catalog-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "catalog-api.name" . }} - chart: {{ template "catalog-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "catalog-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "catalog-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: grpc - containerPort: 81 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/catalog-api/templates/service.yaml b/deploy/k8s/archived/helm/catalog-api/templates/service.yaml deleted file mode 100644 index f634a7088..000000000 --- a/deploy/k8s/archived/helm/catalog-api/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.catalog }} - labels: - app: {{ template "catalog-api.name" . }} - chart: {{ template "catalog-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.grpcPort }} - targetPort: grpc - protocol: TCP - name: grpc - selector: - app: {{ template "catalog-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/catalog-api/values.yaml b/deploy/k8s/archived/helm/catalog-api/values.yaml deleted file mode 100644 index 0de49b7f6..000000000 --- a/deploy/k8s/archived/helm/catalog-api/values.yaml +++ /dev/null @@ -1,63 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /catalog-api - -image: - repository: eshop/catalog.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - grpcPort: 81 - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ConnectionString - key: catalog__ConnectionString - - name: PicBaseUrl - key: catalog__PicBaseUrl - - name: AzureStorageEnabled - key: catalog__AzureStorageEnabled - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' - - name: PORT - value: "80" - - name: GRPC_PORT - value: "81" -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 - diff --git a/deploy/k8s/archived/helm/deploy-all.ps1 b/deploy/k8s/archived/helm/deploy-all.ps1 deleted file mode 100644 index 51d87e720..000000000 --- a/deploy/k8s/archived/helm/deploy-all.ps1 +++ /dev/null @@ -1,149 +0,0 @@ -Param( - [parameter(Mandatory=$false)][string]$registry, - [parameter(Mandatory=$false)][string]$dockerUser, - [parameter(Mandatory=$false)][string]$dockerPassword, - [parameter(Mandatory=$false)][string]$externalDns, - [parameter(Mandatory=$false)][string]$appName="eshop", - [parameter(Mandatory=$false)][bool]$deployInfrastructure=$true, - [parameter(Mandatory=$false)][bool]$deployCharts=$true, - [parameter(Mandatory=$false)][bool]$clean=$true, - [parameter(Mandatory=$false)][string]$aksName="", - [parameter(Mandatory=$false)][string]$aksRg="", - [parameter(Mandatory=$false)][string]$imageTag="latest", - [parameter(Mandatory=$false)][bool]$useLocalk8s=$false, - [parameter(Mandatory=$false)][bool]$useMesh=$false, - [parameter(Mandatory=$false)][string][ValidateSet('Always','IfNotPresent','Never', IgnoreCase=$false)]$imagePullPolicy="Always", - [parameter(Mandatory=$false)][string][ValidateSet('prod','staging','none','custom', IgnoreCase=$false)]$sslSupport = "none", - [parameter(Mandatory=$false)][string]$tlsSecretName = "eshop-tls-custom", - [parameter(Mandatory=$false)][string]$chartsToDeploy="*", - [parameter(Mandatory=$false)][string]$ingressMeshAnnotationsFile="ingress_values_linkerd.yaml" - ) - -function Install-Chart { - Param([string]$chart,[string]$initialOptions, [bool]$customRegistry) - $options=$initialOptions - if ($sslEnabled) { - $options = "$options --set ingress.tls[0].secretName=$tlsSecretName --set ingress.tls[0].hosts={$dns}" - if ($sslSupport -ne "custom") { - $options = "$options --set inf.tls.issuer=$sslIssuer" - } - } - if ($customRegistry) { - $options = "$options --set inf.registry.server=$registry --set inf.registry.login=$dockerUser --set inf.registry.pwd=$dockerPassword --set inf.registry.secretName=eshop-docker-scret" - } - - if ($chart -ne "eshop-common" -or $customRegistry) { # eshop-common is ignored when no secret must be deployed - $command = "install $options --name=$appName-$chart $chart" - Write-Host "Helm Command: helm $command" -ForegroundColor Gray - Invoke-Expression 'cmd /c "helm $command"' - } -} - -$dns = $externalDns -$sslEnabled=$false -$sslIssuer="" - -if ($sslSupport -eq "staging") { - $sslEnabled=$true - $tlsSecretName="eshop-letsencrypt-staging" - $sslIssuer="letsencrypt-staging" -} -elseif ($sslSupport -eq "prod") { - $sslEnabled=$true - $tlsSecretName="eshop-letsencrypt-prod" - $sslIssuer="letsencrypt-prod" -} -elseif ($sslSupport -eq "custom") { - $sslEnabled=$true -} - -$ingressValuesFile="ingress_values.yaml" - -if ($useLocalk8s -eq $true) { - $ingressValuesFile="ingress_values_dockerk8s.yaml" - $dns="localhost" -} - -if ($externalDns -eq "aks") { - if ([string]::IsNullOrEmpty($aksName) -or [string]::IsNullOrEmpty($aksRg)) { - Write-Host "Error: When using -dns aks, MUST set -aksName and -aksRg too." -ForegroundColor Red - exit 1 - } - Write-Host "Getting DNS of AKS of AKS $aksName (in resource group $aksRg)..." -ForegroundColor Green - $dns = $(az aks show -n $aksName -g $aksRg --query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName) - if ([string]::IsNullOrEmpty($dns)) { - Write-Host "Error getting DNS of AKS $aksName (in resource group $aksRg). Please ensure AKS has httpRouting enabled AND Azure CLI is logged & in version 2.0.37 or higher" -ForegroundColor Red - exit 1 - } - $dns = $dns -replace '[\"]' - Write-Host "DNS base found is $dns. Will use $appName.$dns for the app!" -ForegroundColor Green - $dns = "$appName.$dns" -} - -# Initialization & check commands -if ([string]::IsNullOrEmpty($dns)) { - Write-Host "No DNS specified. Ingress resources will be bound to public ip" -ForegroundColor Yellow - if ($sslEnabled) { - Write-Host "Can't bound SSL to public IP. DNS is mandatory when using TLS" -ForegroundColor Red - exit 1 - } -} - -if ($useLocalk8s -and $sslEnabled) { - Write-Host "SSL can'be enabled on local K8s." -ForegroundColor Red - exit 1 -} - -if ($clean) { - Write-Host "Cleaning previous helm releases..." -ForegroundColor Green - helm delete --purge $(helm ls -q eshop) - Write-Host "Previous releases deleted" -ForegroundColor Green -} - -$useCustomRegistry=$false - -if (-not [string]::IsNullOrEmpty($registry)) { - $useCustomRegistry=$true - if ([string]::IsNullOrEmpty($dockerUser) -or [string]::IsNullOrEmpty($dockerPassword)) { - Write-Host "Error: Must use -dockerUser AND -dockerPassword if specifying custom registry" -ForegroundColor Red - exit 1 - } -} - -Write-Host "Begin eShopOnContainers installation using Helm" -ForegroundColor Green - -$infras = ("sql-data", "nosql-data", "rabbitmq", "keystore-data", "basket-data") -$charts = ("eshop-common", "basket-api","catalog-api", "identity-api", "mobileshoppingagg","ordering-api","ordering-backgroundtasks","ordering-signalrhub", "payment-api", "webmvc", "webshoppingagg", "webspa", "webstatus", "webhooks-api", "webhooks-web") -$gateways = ("apigwmm", "apigwms", "apigwwm", "apigwws") - -if ($deployInfrastructure) { - foreach ($infra in $infras) { - Write-Host "Installing infrastructure: $infra" -ForegroundColor Green - helm install --values app.yaml --values inf.yaml --values $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set "ingress.hosts={$dns}" --name="$appName-$infra" $infra - } -} -else { - Write-Host "eShopOnContainers infrastructure (bbdd, redis, ...) charts aren't installed (-deployCharts is false)" -ForegroundColor Yellow -} - -if ($deployCharts) { - foreach ($chart in $charts) { - if ($chartsToDeploy -eq "*" -or $chartsToDeploy.Contains($chart)) { - Write-Host "Installing: $chart" -ForegroundColor Green - Install-Chart $chart "-f app.yaml --values inf.yaml -f $ingressValuesFile -f $ingressMeshAnnotationsFile --set app.name=$appName --set inf.k8s.dns=$dns --set ingress.hosts={$dns} --set image.tag=$imageTag --set image.pullPolicy=$imagePullPolicy --set inf.tls.enabled=$sslEnabled --set inf.mesh.enabled=$useMesh --set inf.k8s.local=$useLocalk8s" $useCustomRegistry - } - } - - foreach ($chart in $gateways) { - if ($chartsToDeploy -eq "*" -or $chartsToDeploy.Contains($chart)) { - Write-Host "Installing Api Gateway Chart: $chart" -ForegroundColor Green - Install-Chart $chart "-f app.yaml -f inf.yaml -f $ingressValuesFile --set app.name=$appName --set inf.k8s.dns=$dns --set image.pullPolicy=$imagePullPolicy --set inf.mesh.enabled=$useMesh --set ingress.hosts={$dns} --set inf.tls.enabled=$sslEnabled" $false - - } - } -} -else { - Write-Host "eShopOnContainers non-infrastructure charts aren't installed (-deployCharts is false)" -ForegroundColor Yellow -} - -Write-Host "helm charts installed." -ForegroundColor Green diff --git a/deploy/k8s/archived/helm/eshop-common/.helmignore b/deploy/k8s/archived/helm/eshop-common/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/eshop-common/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/eshop-common/Chart.yaml b/deploy/k8s/archived/helm/eshop-common/Chart.yaml deleted file mode 100644 index cd5e7b2fe..000000000 --- a/deploy/k8s/archived/helm/eshop-common/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: eshop-common -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/eshop-common/templates/NOTES.txt b/deploy/k8s/archived/helm/eshop-common/templates/NOTES.txt deleted file mode 100644 index 1cc59f58a..000000000 --- a/deploy/k8s/archived/helm/eshop-common/templates/NOTES.txt +++ /dev/null @@ -1,7 +0,0 @@ -Common eShop resources installed: - -{{- if .Values.inf.registry -}} -* Docker registry secret ({{ .Values.inf.registry.secretName }}) -{{- end -}} - -+++ Done +++ \ No newline at end of file diff --git a/deploy/k8s/archived/helm/eshop-common/templates/_helpers.tpl b/deploy/k8s/archived/helm/eshop-common/templates/_helpers.tpl deleted file mode 100644 index 4a3c6324b..000000000 --- a/deploy/k8s/archived/helm/eshop-common/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "eshop-common.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "eshop-common.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "eshop-common.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/eshop-common/templates/_names.tpl b/deploy/k8s/archived/helm/eshop-common/templates/_names.tpl deleted file mode 100644 index 7cdfb80d6..000000000 --- a/deploy/k8s/archived/helm/eshop-common/templates/_names.tpl +++ /dev/null @@ -1,3 +0,0 @@ -{{- define "imagePullSecret" }} -{{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.inf.registry.server (printf "%s:%s" .Values.inf.registry.login .Values.inf.registry.pwd | b64enc) | b64enc }} -{{- end }} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/eshop-common/templates/secret.yaml b/deploy/k8s/archived/helm/eshop-common/templates/secret.yaml deleted file mode 100644 index 285ec85e7..000000000 --- a/deploy/k8s/archived/helm/eshop-common/templates/secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -{{- if .Values.inf.registry -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Values.inf.registry.secretName }} -type: kubernetes.io/dockerconfigjson -data: - .dockerconfigjson: {{ template "imagePullSecret" . }} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/eshop-common/values.yaml b/deploy/k8s/archived/helm/eshop-common/values.yaml deleted file mode 100644 index e69de29bb..000000000 diff --git a/deploy/k8s/archived/helm/identity-api/.helmignore b/deploy/k8s/archived/helm/identity-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/identity-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/identity-api/Chart.yaml b/deploy/k8s/archived/helm/identity-api/Chart.yaml deleted file mode 100644 index 7b9290ada..000000000 --- a/deploy/k8s/archived/helm/identity-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: identity-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/identity-api/templates/NOTES.txt b/deploy/k8s/archived/helm/identity-api/templates/NOTES.txt deleted file mode 100644 index 48fbbe9b4..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/NOTES.txt +++ /dev/null @@ -1,4 +0,0 @@ -eShop Identity API installed. ------------------------------ - -Access this API through ingress. \ No newline at end of file diff --git a/deploy/k8s/archived/helm/identity-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/identity-api/templates/_helpers.tpl deleted file mode 100644 index fb47187b4..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "identity-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "identity-api.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "identity-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/identity-api/templates/_names.tpl b/deploy/k8s/archived/helm/identity-api/templates/_names.tpl deleted file mode 100644 index 39ee485ef..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/_names.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml b/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml deleted file mode 100644 index 7c670f646..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/configmap.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- $name := include "identity-api.fullname" . -}} -{{- $sqlsrv := include "sql-name" . -}} -{{- $mvc_url := include "url-of" (list .Values.app.ingress.entries.mvc .) -}} -{{- $spa_url := include "url-of" (list .Values.app.ingress.entries.spa .) -}} -{{- $basket_url := include "url-of" (list .Values.app.ingress.entries.basket .) -}} -{{- $ordering_url := include "url-of" (list .Values.app.ingress.entries.ordering .) -}} -{{- $mobileshoppingagg := include "url-of" (list .Values.app.ingress.entries.mobileshoppingagg .) -}} -{{- $webhoppingagg := include "url-of" (list .Values.app.ingress.entries.webshoppingagg .) -}} -{{- $xamarincallback := include "url-of" (list "xamarincallback" .) -}} -{{- $webhooks_url := include "url-of" (list .Values.app.ingress.entries.webhooks .) -}} -{{- $webhooksweb_url := include "url-of" (list .Values.app.ingress.entries.webhooksweb .) -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "identity-api.name" . }} - chart: {{ template "identity-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - identity__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.identity.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; - identity__keystore: {{ .Values.inf.redis.keystore.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - mvc_e: http://{{ $mvc_url }} - spa_e: http://{{ $spa_url }} - basket_e: http://{{ $basket_url }} - ordering_e: http://{{ $ordering_url }} - mobileshoppingagg_e: http://{{ $mobileshoppingagg }} - webshoppingagg_e: http://{{ $webhoppingagg }} - xamarin_callback_e: http://{{ $xamarincallback }} - webhooksapi_e: http://{{ $webhooks_url }} - webhooksweb_e: http://{{ $webhooksweb_url }} - enableDevspaces: "{{ .Values.enableDevspaces }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/identity-api/templates/deployment.yaml b/deploy/k8s/archived/helm/identity-api/templates/deployment.yaml deleted file mode 100644 index c6ad69067..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ -{{- $name := include "identity-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "identity-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "identity-api.name" . }} - chart: {{ template "identity-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "identity-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "identity-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/identity-api/templates/ingress-dockerk8s.yaml b/deploy/k8s/archived/helm/identity-api/templates/ingress-dockerk8s.yaml deleted file mode 100644 index b6a8980f2..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/ingress-dockerk8s.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- if .Values.inf.k8s.local -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.identity }} -{{- $name := include "identity-api.fullname" . -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ $name }}-local - labels: - app: {{ template "identity-api.name" . }} - chart: {{ template "identity-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: - rules: - - http: - paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: http - path: {{ $ingressPath }} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/identity-api/templates/ingress.yaml b/deploy/k8s/archived/helm/identity-api/templates/ingress.yaml deleted file mode 100644 index 751636926..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/ingress.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.identity }} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "identity-api.fullname" . }} - labels: - app: {{ template "identity-api.name" . }} - chart: {{ template "identity-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/identity-api/templates/service.yaml b/deploy/k8s/archived/helm/identity-api/templates/service.yaml deleted file mode 100644 index bca200389..000000000 --- a/deploy/k8s/archived/helm/identity-api/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.identity }} - labels: - app: {{ template "identity-api.name" . }} - chart: {{ template "identity-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "identity-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/identity-api/values.yaml b/deploy/k8s/archived/helm/identity-api/values.yaml deleted file mode 100644 index 92fd57283..000000000 --- a/deploy/k8s/archived/helm/identity-api/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /identity - -image: - repository: eshop/identity.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: true - annotations: {} - hosts: - - chart-example.local - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -env: - urls: - configmap: - - name: ConnectionString - key: identity__ConnectionString - - name: DPConnectionString - key: identity__keystore - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: MvcClient - key: mvc_e - - name: SpaClient - key: spa_e - - name: BasketApiClient - key: basket_e - - name: OrderingApiClient - key: ordering_e - - name: MobileShoppingAggClient - key: mobileshoppingagg_e - - name: WebShoppingAggClient - key: webshoppingagg_e - - name: XamarinCallback - key: xamarin_callback_e - - name: WebhooksApiClient - key: webhooksapi_e - - name: WebhooksWebClient - key: webhooksweb_e - - name: EnableDevspaces - key: enableDevspaces - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' - - name: IsClusterEnv - value: 'True' - -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 - -enableDevspaces: "false" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/inf.yaml b/deploy/k8s/archived/helm/inf.yaml deleted file mode 100644 index 1ce48d67e..000000000 --- a/deploy/k8s/archived/helm/inf.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# This helm values file defines all infrastructure used by eShopOnContainers. -# It is used on all charts, so ** MUST BE INCLUDED ** on every deployment - -inf: - mesh: - enabled: false # True to enable Linkerd (set by deploy-all.ps1) - tls: - enabled: false # True to enable TLS (set by deploy-all.ps1) - issuer: "" # cert-manager issuer to use for retrieving certs (set by deploy-all.ps1) - sql: # inf.sql defines the sql server databases & logins -# host: my-sql-server # Uncomment to specify a custom sql-server to be used. By default "sql-data-" will be used - common: - user: sa # SQL user - pwd: Pass@word # SQL pwd - pid: Developer - catalog: # inf.sql.catalog: settings for the catalog-api sql (user, pwd, db) - db: CatalogDb # Catalog API SQL db name - ordering: # inf.sql.ordering: settings for the ordering-api sql (user, pwd, db) - db: OrderingDb # Ordering API SQL db name - identity: - db: IdentityDb # Ordering API SQL db name - webhooks: - db: WebhooksDb # Webhooks DB - redis: # inf.redis defines the redis' connection strings - basket: - svc: basket-data # Name of k8s svc for basket redis - constr: basket-data # Connection string to Redis used by Basket API - keystore: - svc: keystore-data # Name of k8s svc for keystore-data redis - constr: keystore-data # Connection string to Redis used as a Keystore (by Identity API) - eventbus: - svc: rabbitmq # Name of k8s svc for rabbitmq - constr: rabbitmq # Event bus connection string - useAzure: false # true if use Azure Service Bus. False if RabbitMQ - appinsights: - key: "" # App insights to use - k8s: # inf.k8s defines Kubernetes cluster global config - dns: "" # k8s external DNS. This value or ip value MUST BE PROVIDED - local: false # True when deploying on "local K8s" provided by Docker Desktop. - misc: # inf.misc contains miscellaneous configuration related to infrastructure - useAzureStorage: false # If catalog api uses azure storage or not -# registry: # Uncomment "registry" to specify registry secret -# secretName: # secretName is the name of the secret inside k8s -# server: # Registry login server -# login: # User login -# pwd: # User pwd - diff --git a/deploy/k8s/archived/helm/ingress_values.yaml b/deploy/k8s/archived/helm/ingress_values.yaml deleted file mode 100644 index 5f4d653c0..000000000 --- a/deploy/k8s/archived/helm/ingress_values.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# This file contains common ingress annotations when using AKS with Http Application Routing - -ingress: - annotations: - kubernetes.io/ingress.class: addon-http-application-routing - ingress.kubernetes.io/ssl-redirect: "false" - nginx.ingress.kubernetes.io/ssl-redirect: "false" - diff --git a/deploy/k8s/archived/helm/ingress_values_dockerk8s.yaml b/deploy/k8s/archived/helm/ingress_values_dockerk8s.yaml deleted file mode 100644 index f69af8a5b..000000000 --- a/deploy/k8s/archived/helm/ingress_values_dockerk8s.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# This file contains common ingress annotations when using Kubernetes included in Docker Desktop - -ingress: - annotations: - kubernetes.io/ingress.class: "nginx" - ingress.kubernetes.io/ssl-redirect: "false" - nginx.ingress.kubernetes.io/ssl-redirect: "false" diff --git a/deploy/k8s/archived/helm/ingress_values_linkerd.yaml b/deploy/k8s/archived/helm/ingress_values_linkerd.yaml deleted file mode 100644 index f85a3a57f..000000000 --- a/deploy/k8s/archived/helm/ingress_values_linkerd.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# This file contains extra annotations to make Linkerd work with ingress. -# ingress.mesh.annotations are inserted into ingress.annotations of the resource being generated, if mesh is deployed -# -# It is designed to work with NGINX ingress controller or the Http Application Routing -# -# Check https://linkerd.io/2/tasks/using-ingress/ for more info or other ingress controllers -# -# If using your custom file, use -ingressMeshAnnotationsFile parameter in deploy-all.ps1 - -ingress: - mesh: - annotations: - nginx.ingress.kubernetes.io/configuration-snippet: | - proxy_set_header l5d-dst-override $service_name.$namespace.svc.cluster.local:$service_port; - proxy_hide_header l5d-remote-ip; - proxy_hide_header l5d-server-id; \ No newline at end of file diff --git a/deploy/k8s/archived/helm/keystore-data/.helmignore b/deploy/k8s/archived/helm/keystore-data/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/keystore-data/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/keystore-data/Chart.yaml b/deploy/k8s/archived/helm/keystore-data/Chart.yaml deleted file mode 100644 index 0cfa515f9..000000000 --- a/deploy/k8s/archived/helm/keystore-data/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: keystore-data -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/keystore-data/templates/NOTES.txt b/deploy/k8s/archived/helm/keystore-data/templates/NOTES.txt deleted file mode 100644 index bec3a1f0f..000000000 --- a/deploy/k8s/archived/helm/keystore-data/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Redis for keystore data installed ----------------------------------------- - -Redis is not directly exposed outside cluster. If need to access it from outside use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "keystore-data.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/keystore-data/templates/_helpers.tpl b/deploy/k8s/archived/helm/keystore-data/templates/_helpers.tpl deleted file mode 100644 index 18786752f..000000000 --- a/deploy/k8s/archived/helm/keystore-data/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "keystore-data.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "keystore-data.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "keystore-data.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/keystore-data/templates/deployment.yaml b/deploy/k8s/archived/helm/keystore-data/templates/deployment.yaml deleted file mode 100644 index 34f1fe074..000000000 --- a/deploy/k8s/archived/helm/keystore-data/templates/deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "keystore-data.fullname" . }} - labels: - app: {{ template "keystore-data.name" . }} - chart: {{ template "keystore-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "keystore-data.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "keystore-data.name" . }} - release: {{ .Release.Name }} - spec: - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 6379 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} diff --git a/deploy/k8s/archived/helm/keystore-data/templates/service.yaml b/deploy/k8s/archived/helm/keystore-data/templates/service.yaml deleted file mode 100644 index 38e9a4273..000000000 --- a/deploy/k8s/archived/helm/keystore-data/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.inf.redis.keystore.svc }} - labels: - app: {{ template "keystore-data.name" . }} - chart: {{ template "keystore-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "keystore-data.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/keystore-data/values.yaml b/deploy/k8s/archived/helm/keystore-data/values.yaml deleted file mode 100644 index 17cc75ee7..000000000 --- a/deploy/k8s/archived/helm/keystore-data/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -replicaCount: 1 - -image: - repository: redis - tag: 4.0.10 - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 6379 - - -resources: {} - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/.helmignore b/deploy/k8s/archived/helm/mobileshoppingagg/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/Chart.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/Chart.yaml deleted file mode 100644 index 957edd619..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: mobileshoppingagg -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt b/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt deleted file mode 100644 index e7e5081ea..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Mobile Shopping Aggregator is installed ----------------------------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "mobileshoppingagg.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/_helpers.tpl b/deploy/k8s/archived/helm/mobileshoppingagg/templates/_helpers.tpl deleted file mode 100644 index b3aace0e7..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "mobileshoppingagg.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "mobileshoppingagg.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "mobileshoppingagg.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/_names.tpl b/deploy/k8s/archived/helm/mobileshoppingagg/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml deleted file mode 100644 index b55afbdb2..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/configmap.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- $name := include "mobileshoppingagg.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "mobileshoppingagg.name" . }} - chart: {{ template "mobileshoppingagg.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - mobileshoppingagg__keystore: {{ .Values.inf.redis.keystore.constr }} - internalurls__basket: http://{{ .Values.app.svc.basket }} - internalurls__catalog: http://{{ .Values.app.svc.catalog }} - internalurls__identity: http://{{ .Values.app.svc.identity }} - internalurls__ordering: http://{{ .Values.app.svc.ordering }} - internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc - internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc - internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - internalurls__grpcBasket: "http://{{ .Values.app.svc.basket }}:{{ .Values.service.grpcPort }}" - internalurls__grpcCatalog: "http://{{ .Values.app.svc.catalog }}:{{ .Values.service.grpcPort }}" - internalurls__grpcOrdering: "http://{{ .Values.app.svc.ordering }}:{{ .Values.service.grpcPort }}" diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/deployment.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/templates/deployment.yaml deleted file mode 100644 index 41e1fa75c..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ -{{- $name := include "mobileshoppingagg.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "mobileshoppingagg.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "mobileshoppingagg.name" . }} - chart: {{ template "mobileshoppingagg.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "mobileshoppingagg.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "mobileshoppingagg.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/templates/service.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/templates/service.yaml deleted file mode 100644 index ef6726e88..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.mobileshoppingagg }} - labels: - app: {{ template "mobileshoppingagg.name" . }} - chart: {{ template "mobileshoppingagg.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "mobileshoppingagg.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml b/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml deleted file mode 100644 index fc7ce7a38..000000000 --- a/deploy/k8s/archived/helm/mobileshoppingagg/values.yaml +++ /dev/null @@ -1,81 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /mobileshoppingagg - -image: - repository: eshop/mobileshoppingagg - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - grpcPort: 81 - -ingress: - enabled: false - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: urls__basket - key: internalurls__basket - - name: urls__catalog - key: internalurls__catalog - - name: urls__orders - key: internalurls__ordering - - name: urls__identity - key: internalurls__identity - - name: CatalogUrlHC - key: internalurls__catalog__hc - - name: BasketUrlHC - key: internalurls__basket__hc - - name: IdentityUrlHC - key: internalurls__identity__hc - - name: OrderingUrlHC - key: internalurls__ordering__hc - - name: PaymentUrlHC - key: internalurls__payment__hc - - name: urls__grpcBasket - key: internalurls__grpcBasket - - name: urls__grpcCatalog - key: internalurls__grpcCatalog - - name: urls__grpcOrdering - key: internalurls__grpcOrdering - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: ASPNETCORE_URLS - value: http://0.0.0.0:80 - - name: OrchestratorType - value: 'K8S' - - name: IsClusterEnv - value: 'True' -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 diff --git a/deploy/k8s/archived/helm/nosql-data/.helmignore b/deploy/k8s/archived/helm/nosql-data/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/nosql-data/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/nosql-data/Chart.yaml b/deploy/k8s/archived/helm/nosql-data/Chart.yaml deleted file mode 100644 index 848a11cbb..000000000 --- a/deploy/k8s/archived/helm/nosql-data/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: nosql-data -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/nosql-data/templates/NOTES.txt b/deploy/k8s/archived/helm/nosql-data/templates/NOTES.txt deleted file mode 100644 index 116c3c4e0..000000000 --- a/deploy/k8s/archived/helm/nosql-data/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop MongoDb Installed ------------------------ - -MongoDb is not exposed outside the cluster. If need to access it from outside, use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "nosql-data.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/nosql-data/templates/_helpers.tpl b/deploy/k8s/archived/helm/nosql-data/templates/_helpers.tpl deleted file mode 100644 index 99be734f7..000000000 --- a/deploy/k8s/archived/helm/nosql-data/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "nosql-data.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "nosql-data.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "nosql-data.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/nosql-data/templates/_names.tpl b/deploy/k8s/archived/helm/nosql-data/templates/_names.tpl deleted file mode 100644 index 56fb974fc..000000000 --- a/deploy/k8s/archived/helm/nosql-data/templates/_names.tpl +++ /dev/null @@ -1,8 +0,0 @@ - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/nosql-data/templates/deployment.yaml b/deploy/k8s/archived/helm/nosql-data/templates/deployment.yaml deleted file mode 100644 index 9b1f32319..000000000 --- a/deploy/k8s/archived/helm/nosql-data/templates/deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "nosql-data.fullname" . }} - labels: - app: {{ template "nosql-data.name" . }} - chart: {{ template "nosql-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "nosql-data.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "nosql-data.name" . }} - release: {{ .Release.Name }} - spec: - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 27017 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} diff --git a/deploy/k8s/archived/helm/nosql-data/templates/service.yaml b/deploy/k8s/archived/helm/nosql-data/templates/service.yaml deleted file mode 100644 index 478cadfea..000000000 --- a/deploy/k8s/archived/helm/nosql-data/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "mongo-name" . }} - labels: - app: {{ template "nosql-data.name" . }} - chart: {{ template "nosql-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "nosql-data.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/nosql-data/values.yaml b/deploy/k8s/archived/helm/nosql-data/values.yaml deleted file mode 100644 index 1a380e6b4..000000000 --- a/deploy/k8s/archived/helm/nosql-data/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -replicaCount: 1 - -image: - repository: mongo - tag: 3.6.5-jessie - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 27017 - - -resources: {} - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/deploy/k8s/archived/helm/ordering-api/.helmignore b/deploy/k8s/archived/helm/ordering-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/ordering-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/ordering-api/Chart.yaml b/deploy/k8s/archived/helm/ordering-api/Chart.yaml deleted file mode 100644 index b65ca4b9a..000000000 --- a/deploy/k8s/archived/helm/ordering-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: ordering-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/ordering-api/templates/NOTES.txt b/deploy/k8s/archived/helm/ordering-api/templates/NOTES.txt deleted file mode 100644 index 43bfd2fdf..000000000 --- a/deploy/k8s/archived/helm/ordering-api/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Ordering API installed. ------------------------------ - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "ordering-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 diff --git a/deploy/k8s/archived/helm/ordering-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/ordering-api/templates/_helpers.tpl deleted file mode 100644 index 978c08c64..000000000 --- a/deploy/k8s/archived/helm/ordering-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "ordering-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "ordering-api.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "ordering-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/ordering-api/templates/_names.tpl b/deploy/k8s/archived/helm/ordering-api/templates/_names.tpl deleted file mode 100644 index 39ee485ef..000000000 --- a/deploy/k8s/archived/helm/ordering-api/templates/_names.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/ordering-api/templates/configmap.yaml b/deploy/k8s/archived/helm/ordering-api/templates/configmap.yaml deleted file mode 100644 index e93dddd5c..000000000 --- a/deploy/k8s/archived/helm/ordering-api/templates/configmap.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- $name := include "ordering-api.fullname" . -}} -{{- $sqlsrv := include "sql-name" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "ordering-api.name" . }} - chart: {{ template "ordering-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - ordering__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.ordering.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; - urls__IdentityUrl: http://{{ .Values.app.svc.identity }} - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/ordering-api/templates/deployment.yaml b/deploy/k8s/archived/helm/ordering-api/templates/deployment.yaml deleted file mode 100644 index 327040701..000000000 --- a/deploy/k8s/archived/helm/ordering-api/templates/deployment.yaml +++ /dev/null @@ -1,99 +0,0 @@ -{{- $name := include "ordering-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "ordering-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "ordering-api.name" . }} - chart: {{ template "ordering-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "ordering-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "ordering-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - - name: grpc - containerPort: 81 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/ordering-api/templates/service.yaml b/deploy/k8s/archived/helm/ordering-api/templates/service.yaml deleted file mode 100644 index 7c2cb0945..000000000 --- a/deploy/k8s/archived/helm/ordering-api/templates/service.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.ordering }} - labels: - app: {{ template "ordering-api.name" . }} - chart: {{ template "ordering-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.service.grpcPort }} - targetPort: grpc - protocol: TCP - name: grpc - selector: - app: {{ template "ordering-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/ordering-api/values.yaml b/deploy/k8s/archived/helm/ordering-api/values.yaml deleted file mode 100644 index 505ccc379..000000000 --- a/deploy/k8s/archived/helm/ordering-api/values.yaml +++ /dev/null @@ -1,67 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /ordering-api - -image: - repository: eshop/ordering.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - grpcPort: 81 - -ingress: - enabled: false - annotations: {} - hosts: - - chart-example.local - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ConnectionString - key: ordering__ConnectionString - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: IdentityUrl - key: urls__IdentityUrl - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' - - name: PORT - value: "80" - - name: GRPC_PORT - value: "81" -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/.helmignore b/deploy/k8s/archived/helm/ordering-backgroundtasks/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/Chart.yaml b/deploy/k8s/archived/helm/ordering-backgroundtasks/Chart.yaml deleted file mode 100644 index 6ad4f47e6..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: ordering-backgroundtasks -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/NOTES.txt b/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/NOTES.txt deleted file mode 100644 index 54e1b49ea..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/NOTES.txt +++ /dev/null @@ -1,3 +0,0 @@ -eShop Ordering Background Tasks installed. ------------------------------------------- - diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/_helpers.tpl b/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/_helpers.tpl deleted file mode 100644 index e61b78285..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "ordering-backgroundtasks.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "ordering-backgroundtasks.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "ordering-backgroundtasks.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/_names.tpl b/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/_names.tpl deleted file mode 100644 index 39ee485ef..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/_names.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/configmap.yaml b/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/configmap.yaml deleted file mode 100644 index 928692c57..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/configmap.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- $name := include "ordering-backgroundtasks.fullname" . -}} -{{- $sqlsrv := include "sql-name" . -}} -{{- $cfgname := printf "cfg-%s" $name | trunc 63 }} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "{{ $cfgname }}" - labels: - app: {{ template "ordering-backgroundtasks.name" . }} - chart: {{ template "ordering-backgroundtasks.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - ordering__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.ordering.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" - graceperiodmanager__CheckUpdateTime: "{{ .Values.cfg.checkUpdateTime }}" - graceperiodmanager__GracePeriodTime: "{{ .Values.cfg.gracePeriodTime }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/deployment.yaml b/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/deployment.yaml deleted file mode 100644 index d93c7f764..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/deployment.yaml +++ /dev/null @@ -1,92 +0,0 @@ -{{- $name := include "ordering-backgroundtasks.fullname" . -}} -{{- $cfgname := printf "cfg-%s" $name | trunc 63 }} - -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "ordering-backgroundtasks.fullname" . }} - labels: - app: {{ template "ordering-backgroundtasks.name" . }} - chart: {{ template "ordering-backgroundtasks.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "ordering-backgroundtasks.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "ordering-backgroundtasks.name" . }} - release: {{ .Release.Name }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/service.yaml b/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/service.yaml deleted file mode 100644 index d8fcba036..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.orderingbackgroundtasks }} - labels: - app: {{ template "ordering-backgroundtasks.name" . }} - chart: {{ template "ordering-backgroundtasks.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "ordering-backgroundtasks.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/ordering-backgroundtasks/values.yaml b/deploy/k8s/archived/helm/ordering-backgroundtasks/values.yaml deleted file mode 100644 index 18abe99a5..000000000 --- a/deploy/k8s/archived/helm/ordering-backgroundtasks/values.yaml +++ /dev/null @@ -1,68 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /ordering-backgroundtasks - -image: - repository: eshop/ordering.backgroundtasks - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - annotations: {} - hosts: - - chart-example.local - tls: [] - -cfg: - checkUpdateTime: "15000" - gracePeriodTime: "1" - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ConnectionString - key: ordering__ConnectionString - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: CheckUpdateTime - key: graceperiodmanager__CheckUpdateTime - - name: GracePeriodTime - key: graceperiodmanager__GracePeriodTime - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/.helmignore b/deploy/k8s/archived/helm/ordering-signalrhub/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/Chart.yaml b/deploy/k8s/archived/helm/ordering-signalrhub/Chart.yaml deleted file mode 100644 index d43e83bf0..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: ordering-signalrhub -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/templates/NOTES.txt b/deploy/k8s/archived/helm/ordering-signalrhub/templates/NOTES.txt deleted file mode 100644 index fc55c9dfa..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Ordering SignalR Hub installed ------------------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "ordering-signalrhub.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/templates/_helpers.tpl b/deploy/k8s/archived/helm/ordering-signalrhub/templates/_helpers.tpl deleted file mode 100644 index 2c11ddb51..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "ordering-signalrhub.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "ordering-signalrhub.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "ordering-signalrhub.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/templates/_names.tpl b/deploy/k8s/archived/helm/ordering-signalrhub/templates/_names.tpl deleted file mode 100644 index 39ee485ef..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/templates/_names.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/templates/configmap.yaml b/deploy/k8s/archived/helm/ordering-signalrhub/templates/configmap.yaml deleted file mode 100644 index bab4ebc94..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/templates/configmap.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- $name := include "ordering-signalrhub.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "ordering-signalrhub.name" . }} - chart: {{ template "ordering-signalrhub.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" - signalr__StoreConnectionString: {{ .Values.inf.redis.keystore.constr }} - urls__IdentityUrl: http://{{ $identity }} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/templates/deployment.yaml b/deploy/k8s/archived/helm/ordering-signalrhub/templates/deployment.yaml deleted file mode 100644 index af3867ea5..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/templates/deployment.yaml +++ /dev/null @@ -1,70 +0,0 @@ -{{- $name := include "ordering-signalrhub.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "ordering-signalrhub.fullname" . }} - labels: - app: {{ template "ordering-signalrhub.name" . }} - chart: {{ template "ordering-signalrhub.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "ordering-signalrhub.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "ordering-signalrhub.name" . }} - release: {{ .Release.Name }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/templates/service.yaml b/deploy/k8s/archived/helm/ordering-signalrhub/templates/service.yaml deleted file mode 100644 index 501539923..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.orderingsignalrhub }} - labels: - app: {{ template "ordering-signalrhub.name" . }} - chart: {{ template "ordering-signalrhub.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "ordering-signalrhub.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/ordering-signalrhub/values.yaml b/deploy/k8s/archived/helm/ordering-signalrhub/values.yaml deleted file mode 100644 index 19099b147..000000000 --- a/deploy/k8s/archived/helm/ordering-signalrhub/values.yaml +++ /dev/null @@ -1,57 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /ordering-signalrhub - -image: - repository: eshop/ordering.signalrhub - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - annotations: {} - hosts: - - chart-example.local - tls: [] - -cfg: - checkUpdateTime: "15000" - gracePeriodTime: "1" - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: IdentityUrl - key: urls__IdentityUrl - - name: SignalrStoreConnectionString - key: signalr__StoreConnectionString - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' - - name: IsClusterEnv - values: 'True' - diff --git a/deploy/k8s/archived/helm/payment-api/.helmignore b/deploy/k8s/archived/helm/payment-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/payment-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/payment-api/Chart.yaml b/deploy/k8s/archived/helm/payment-api/Chart.yaml deleted file mode 100644 index b7dba9341..000000000 --- a/deploy/k8s/archived/helm/payment-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: payment-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/payment-api/templates/NOTES.txt b/deploy/k8s/archived/helm/payment-api/templates/NOTES.txt deleted file mode 100644 index 6d178f344..000000000 --- a/deploy/k8s/archived/helm/payment-api/templates/NOTES.txt +++ /dev/null @@ -1,9 +0,0 @@ -eShop Payment API installed. ----------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "payment-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 - diff --git a/deploy/k8s/archived/helm/payment-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/payment-api/templates/_helpers.tpl deleted file mode 100644 index 2f98d7ea2..000000000 --- a/deploy/k8s/archived/helm/payment-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "payment-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "payment-api.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "payment-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/payment-api/templates/_names.tpl b/deploy/k8s/archived/helm/payment-api/templates/_names.tpl deleted file mode 100644 index 39ee485ef..000000000 --- a/deploy/k8s/archived/helm/payment-api/templates/_names.tpl +++ /dev/null @@ -1,51 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/payment-api/templates/configmap.yaml b/deploy/k8s/archived/helm/payment-api/templates/configmap.yaml deleted file mode 100644 index 3bdb95c0f..000000000 --- a/deploy/k8s/archived/helm/payment-api/templates/configmap.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- $name := include "payment-api.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "payment-api.name" . }} - chart: {{ template "payment-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/payment-api/templates/deployment.yaml b/deploy/k8s/archived/helm/payment-api/templates/deployment.yaml deleted file mode 100644 index f83eb37da..000000000 --- a/deploy/k8s/archived/helm/payment-api/templates/deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ -{{- $name := include "payment-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "payment-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "payment-api.name" . }} - chart: {{ template "payment-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "payment-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "payment-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/payment-api/templates/service.yaml b/deploy/k8s/archived/helm/payment-api/templates/service.yaml deleted file mode 100644 index 14fc7479c..000000000 --- a/deploy/k8s/archived/helm/payment-api/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.payment }} - labels: - app: {{ template "payment-api.name" . }} - chart: {{ template "payment-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "payment-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/payment-api/values.yaml b/deploy/k8s/archived/helm/payment-api/values.yaml deleted file mode 100644 index 341e4e1a9..000000000 --- a/deploy/k8s/archived/helm/payment-api/values.yaml +++ /dev/null @@ -1,56 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /payment-api - -image: - repository: eshop/payment.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: false - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 diff --git a/deploy/k8s/archived/helm/rabbitmq/.helmignore b/deploy/k8s/archived/helm/rabbitmq/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/rabbitmq/Chart.yaml b/deploy/k8s/archived/helm/rabbitmq/Chart.yaml deleted file mode 100644 index 2d955858e..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: rabbitmq -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/rabbitmq/templates/NOTES.txt b/deploy/k8s/archived/helm/rabbitmq/templates/NOTES.txt deleted file mode 100644 index 49edf7f9c..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop rabbitmq installed -------------------------- - -rabbitmq is not directly exposed outside cluster. If need to access it from outside use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "rabbitmq.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/rabbitmq/templates/_helpers.tpl b/deploy/k8s/archived/helm/rabbitmq/templates/_helpers.tpl deleted file mode 100644 index bbbb2e33d..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "rabbitmq.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "rabbitmq.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "rabbitmq.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/rabbitmq/templates/_names.tpl b/deploy/k8s/archived/helm/rabbitmq/templates/_names.tpl deleted file mode 100644 index be0a9b800..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/templates/_names.tpl +++ /dev/null @@ -1,8 +0,0 @@ - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "rabbitmq" -}} -{{- end -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/rabbitmq/templates/deployment.yaml b/deploy/k8s/archived/helm/rabbitmq/templates/deployment.yaml deleted file mode 100644 index 9819a6455..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/templates/deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "rabbitmq.fullname" . }} - labels: - app: {{ template "rabbitmq.name" . }} - chart: {{ template "rabbitmq.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "rabbitmq.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "rabbitmq.name" . }} - release: {{ .Release.Name }} - spec: - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 5672 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} diff --git a/deploy/k8s/archived/helm/rabbitmq/templates/service.yaml b/deploy/k8s/archived/helm/rabbitmq/templates/service.yaml deleted file mode 100644 index 5de39e0a8..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.inf.eventbus.svc }} - labels: - app: {{ template "rabbitmq.name" . }} - chart: {{ template "rabbitmq.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "rabbitmq.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/rabbitmq/values.yaml b/deploy/k8s/archived/helm/rabbitmq/values.yaml deleted file mode 100644 index 5e9efd521..000000000 --- a/deploy/k8s/archived/helm/rabbitmq/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -replicaCount: 1 - -image: - repository: rabbitmq - tag: 3-management - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 5672 - - -resources: {} - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/deploy/k8s/archived/helm/sql-data/.helmignore b/deploy/k8s/archived/helm/sql-data/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/sql-data/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/sql-data/Chart.yaml b/deploy/k8s/archived/helm/sql-data/Chart.yaml deleted file mode 100644 index 6e5d726c5..000000000 --- a/deploy/k8s/archived/helm/sql-data/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: sql-data -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/sql-data/templates/NOTES.txt b/deploy/k8s/archived/helm/sql-data/templates/NOTES.txt deleted file mode 100644 index 468a155b0..000000000 --- a/deploy/k8s/archived/helm/sql-data/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop SQL Server Installed --------------------------- - -SQL server is not exposed outside the cluster. If need to access it from outside, use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "sql-data.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 \ No newline at end of file diff --git a/deploy/k8s/archived/helm/sql-data/templates/_helpers.tpl b/deploy/k8s/archived/helm/sql-data/templates/_helpers.tpl deleted file mode 100644 index ee953f2f8..000000000 --- a/deploy/k8s/archived/helm/sql-data/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "sql-data.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "sql-data.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "sql-data.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/sql-data/templates/_names.tpl b/deploy/k8s/archived/helm/sql-data/templates/_names.tpl deleted file mode 100644 index dc35d62fe..000000000 --- a/deploy/k8s/archived/helm/sql-data/templates/_names.tpl +++ /dev/null @@ -1,8 +0,0 @@ - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/sql-data/templates/deployment.yaml b/deploy/k8s/archived/helm/sql-data/templates/deployment.yaml deleted file mode 100644 index 4b2f589ef..000000000 --- a/deploy/k8s/archived/helm/sql-data/templates/deployment.yaml +++ /dev/null @@ -1,50 +0,0 @@ -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "sql-data.fullname" . }} - labels: - app: {{ template "sql-data.name" . }} - chart: {{ template "sql-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "sql-data.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "sql-data.name" . }} - release: {{ .Release.Name }} - spec: - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: ACCEPT_EULA - value: "Y" - - name: MSSQL_PID - value: {{ .Values.inf.sql.common.pid }} - - name: MSSQL_SA_PASSWORD - value: {{ .Values.inf.sql.common.pwd }} - ports: - - name: http - containerPort: 1433 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} diff --git a/deploy/k8s/archived/helm/sql-data/templates/service.yaml b/deploy/k8s/archived/helm/sql-data/templates/service.yaml deleted file mode 100644 index b9b8d59fc..000000000 --- a/deploy/k8s/archived/helm/sql-data/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "sql-name" . }} - labels: - app: {{ template "sql-data.name" . }} - chart: {{ template "sql-data.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "sql-data.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/sql-data/values.yaml b/deploy/k8s/archived/helm/sql-data/values.yaml deleted file mode 100644 index 0ed76556a..000000000 --- a/deploy/k8s/archived/helm/sql-data/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -replicaCount: 1 - -image: - repository: microsoft/mssql-server-linux - tag: 2017-CU7 - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 1433 - - -resources: {} - -nodeSelector: {} - -tolerations: [] - -affinity: {} diff --git a/deploy/k8s/archived/helm/tls-support/.helmignore b/deploy/k8s/archived/helm/tls-support/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/tls-support/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/tls-support/Chart.yaml b/deploy/k8s/archived/helm/tls-support/Chart.yaml deleted file mode 100644 index e21e04e95..000000000 --- a/deploy/k8s/archived/helm/tls-support/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: tt-ssl -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/tls-support/templates/_helpers.tpl b/deploy/k8s/archived/helm/tls-support/templates/_helpers.tpl deleted file mode 100644 index 5088703f0..000000000 --- a/deploy/k8s/archived/helm/tls-support/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "tt-tls.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "tt-tls.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "tt-tls.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/tls-support/templates/issuer.yaml b/deploy/k8s/archived/helm/tls-support/templates/issuer.yaml deleted file mode 100644 index ae9587198..000000000 --- a/deploy/k8s/archived/helm/tls-support/templates/issuer.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: cert-manager.io/v1alpha2 -kind: Issuer -metadata: - name: {{ .Values.issuerName }} - namespace: default - environment: {{ .Values.environment }} - app: {{ .Values.applicationName }} -spec: - acme: - server: {{ .Values.server }} - email: not@used.com - privateKeySecretRef: - name: {{ .Values.issuerSecretName }} - solvers: - - http01: - ingress: - class: {{ .Values.ingressClass }} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/tls-support/values-prod.yaml b/deploy/k8s/archived/helm/tls-support/values-prod.yaml deleted file mode 100644 index fb577b9b7..000000000 --- a/deploy/k8s/archived/helm/tls-support/values-prod.yaml +++ /dev/null @@ -1,8 +0,0 @@ -applicationName: eshop -issuerName: letsencrypt-prod -certName: eshop-cert-prod -environment: prod -server: https://acme-v02.api.letsencrypt.org/directory -certSecretName: eshop-letsencrypt-prod -issuerSecretName: letsencrypt-prod -ingressClass: addon-http-application-routing \ No newline at end of file diff --git a/deploy/k8s/archived/helm/tls-support/values-staging.yaml b/deploy/k8s/archived/helm/tls-support/values-staging.yaml deleted file mode 100644 index 89dcd6654..000000000 --- a/deploy/k8s/archived/helm/tls-support/values-staging.yaml +++ /dev/null @@ -1,8 +0,0 @@ -applicationName: eshop -issuerName: letsencrypt-staging -certName: eshop-cert-staging -environment: staging -server: https://acme-staging-v02.api.letsencrypt.org/directory -certSecretName: eshop-letsencrypt-staging -issuerSecretName: letsencrypt-staging -ingressClass: addon-http-application-routing \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webhooks-api/.helmignore b/deploy/k8s/archived/helm/webhooks-api/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/webhooks-api/Chart.yaml b/deploy/k8s/archived/helm/webhooks-api/Chart.yaml deleted file mode 100644 index f8e950782..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: webhooks-api -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/NOTES.txt b/deploy/k8s/archived/helm/webhooks-api/templates/NOTES.txt deleted file mode 100644 index 818b99d1b..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Ordering API installed. ------------------------------ - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "webhooks-api.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/_helpers.tpl b/deploy/k8s/archived/helm/webhooks-api/templates/_helpers.tpl deleted file mode 100644 index 3742516b7..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "webhooks-api.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webhooks-api.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webhooks-api.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/_names.tpl b/deploy/k8s/archived/helm/webhooks-api/templates/_names.tpl deleted file mode 100644 index 752355276..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/_names.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} - - -{{- define "protocol" -}} -{{- if .Values.inf.tls.enabled -}} -{{- printf "%s" "https" -}} -{{- else -}} -{{- printf "%s" "http" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/configmap.yaml b/deploy/k8s/archived/helm/webhooks-api/templates/configmap.yaml deleted file mode 100644 index 05b9b7f57..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- $name := include "webhooks-api.fullname" . -}} -{{- $sqlsrv := include "sql-name" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $protocol := include "protocol" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "webhooks-api.name" . }} - chart: {{ template "webhooks-api.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - webhooks__ConnectionString: Server={{ $sqlsrv }};Initial Catalog={{ .Values.inf.sql.webhooks.db }};User Id={{ .Values.inf.sql.common.user }};Password={{ .Values.inf.sql.common.pwd }}; - urls__IdentityUrl: http://{{ $identity }} - urls__IdentityUrlExternal: {{ $protocol }}://{{ $identity }} - all__EventBusConnection: {{ .Values.inf.eventbus.constr }} - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/deployment.yaml b/deploy/k8s/archived/helm/webhooks-api/templates/deployment.yaml deleted file mode 100644 index 2ecb885bf..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/deployment.yaml +++ /dev/null @@ -1,75 +0,0 @@ -{{- $name := include "webhooks-api.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "webhooks-api.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "webhooks-api.name" . }} - chart: {{ template "webhooks-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "webhooks-api.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "webhooks-api.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/ingress.yaml b/deploy/k8s/archived/helm/webhooks-api/templates/ingress.yaml deleted file mode 100644 index c7c096b77..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/ingress.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.webhooks }} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "webhooks-api.fullname" . }} - labels: - app: {{ template "webhooks-api.name" . }} - chart: {{ template "webhooks-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/webhooks-api/templates/service.yaml b/deploy/k8s/archived/helm/webhooks-api/templates/service.yaml deleted file mode 100644 index d8a02ba65..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.webhooks }} - labels: - app: {{ template "webhooks-api.name" . }} - chart: {{ template "webhooks-api.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "webhooks-api.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/webhooks-api/values.yaml b/deploy/k8s/archived/helm/webhooks-api/values.yaml deleted file mode 100644 index f6b1957e9..000000000 --- a/deploy/k8s/archived/helm/webhooks-api/values.yaml +++ /dev/null @@ -1,53 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webhooks-api - -image: - repository: eshop/webhooks.api - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: true - annotations: {} - hosts: - - chart-example.local - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ConnectionString - key: webhooks__ConnectionString - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: EventBusConnection - key: all__EventBusConnection - - name: AzureServiceBusEnabled - key: all__UseAzureServiceBus - - name: IdentityUrl - key: urls__IdentityUrl - - name: IdentityUrlExternal - key: urls__IdentityUrlExternal - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' - diff --git a/deploy/k8s/archived/helm/webhooks-web/.helmignore b/deploy/k8s/archived/helm/webhooks-web/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/webhooks-web/Chart.yaml b/deploy/k8s/archived/helm/webhooks-web/Chart.yaml deleted file mode 100644 index 420b4f16d..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: webhooks-web -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/NOTES.txt b/deploy/k8s/archived/helm/webhooks-web/templates/NOTES.txt deleted file mode 100644 index b7f7f97ba..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Ordering API installed. ------------------------------ - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "webhooks-web.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/_helpers.tpl b/deploy/k8s/archived/helm/webhooks-web/templates/_helpers.tpl deleted file mode 100644 index cbc856713..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "webhooks-web.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webhooks-web.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webhooks-web.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/_names.tpl b/deploy/k8s/archived/helm/webhooks-web/templates/_names.tpl deleted file mode 100644 index 752355276..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/_names.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} - - -{{- define "protocol" -}} -{{- if .Values.inf.tls.enabled -}} -{{- printf "%s" "https" -}} -{{- else -}} -{{- printf "%s" "http" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/configmap.yaml b/deploy/k8s/archived/helm/webhooks-web/templates/configmap.yaml deleted file mode 100644 index bd09c7c62..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/configmap.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- $name := include "webhooks-web.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $webhooksweb := include "url-of" (list .Values.app.ingress.entries.webhooksweb .) -}} -{{- $webhooks := include "url-of" (list .Values.app.ingress.entries.webhooks .) -}} -{{- $protocol := include "protocol" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "webhooks-web.name" . }} - chart: {{ template "webhooks-web.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - urls__webhooks: {{ $protocol }}://{{ $webhooks }} - identity_e: {{ $protocol }}://{{ $identity }} - webhooksweb_e: {{ $protocol }}://{{ $webhooksweb }} - urls_webhooksweb: http://{{ .Values.app.svc.webhooksweb }} diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/deployment.yaml b/deploy/k8s/archived/helm/webhooks-web/templates/deployment.yaml deleted file mode 100644 index 43d406524..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/deployment.yaml +++ /dev/null @@ -1,75 +0,0 @@ -{{- $name := include "webhooks-web.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "webhooks-web.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "webhooks-web.name" . }} - chart: {{ template "webhooks-web.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "webhooks-web.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "webhooks-web.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/ingress.yaml b/deploy/k8s/archived/helm/webhooks-web/templates/ingress.yaml deleted file mode 100644 index 1e5df8c45..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/ingress.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "webhooks-web.fullname" . }} - labels: - app: {{ template "webhooks-web.name" . }} - chart: {{ template "webhooks-web.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $.Values.app.svc.webhooksweb }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/webhooks-web/templates/service.yaml b/deploy/k8s/archived/helm/webhooks-web/templates/service.yaml deleted file mode 100644 index 873ebcc0e..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.webhooksweb }} - labels: - app: {{ template "webhooks-web.name" . }} - chart: {{ template "webhooks-web.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "webhooks-web.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/webhooks-web/values.yaml b/deploy/k8s/archived/helm/webhooks-web/values.yaml deleted file mode 100644 index 0e5b04b57..000000000 --- a/deploy/k8s/archived/helm/webhooks-web/values.yaml +++ /dev/null @@ -1,52 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webhooks-web - -image: - repository: eshop/webhooks.client - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: true - annotations: {} - hosts: - - chart-example.local - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: WebhooksUrl - key: urls__webhooks - - name: IdentityUrl - key: identity_e - - name: CallbackUrl - key: webhooksweb_e - - name: SelfUrl - key: webhooksweb_e - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Production - - name: OrchestratorType - value: 'K8S' - - name: Token - value: "WebHooks-Demo-Web" # Can use whatever you want - - diff --git a/deploy/k8s/archived/helm/webmvc/.helmignore b/deploy/k8s/archived/helm/webmvc/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/webmvc/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/webmvc/Chart.yaml b/deploy/k8s/archived/helm/webmvc/Chart.yaml deleted file mode 100644 index c63e8924a..000000000 --- a/deploy/k8s/archived/helm/webmvc/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: webmvc -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/webmvc/templates/NOTES.txt b/deploy/k8s/archived/helm/webmvc/templates/NOTES.txt deleted file mode 100644 index 06e02a45d..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop WebMVC installed. ------------------------ diff --git a/deploy/k8s/archived/helm/webmvc/templates/_helpers.tpl b/deploy/k8s/archived/helm/webmvc/templates/_helpers.tpl deleted file mode 100644 index 2e3bcef56..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "webmvc.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webmvc.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webmvc.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/webmvc/templates/_names.tpl b/deploy/k8s/archived/helm/webmvc/templates/_names.tpl deleted file mode 100644 index 605e92e7e..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/_names.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} - -{{- define "protocol" -}} -{{- if .Values.inf.tls.enabled -}} -{{- printf "%s" "https" -}} -{{- else -}} -{{- printf "%s" "http" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml b/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml deleted file mode 100644 index 2062bdabc..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/configmap.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- $name := include "webmvc.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} -{{- $mvc := include "url-of" (list .Values.app.ingress.entries.mvc .) -}} -{{- $protocol := include "protocol" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "webmvc.name" . }} - chart: {{ template "webmvc.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" - webmvc__keystore: {{ .Values.inf.redis.keystore.constr }} - internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }} - internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - urls__apigwws: {{ $protocol }}://{{ $webshoppingapigw }} - urls__mvc: {{ $protocol }}://{{ $mvc }} - urls__IdentityUrl: {{ $protocol }}://{{ $identity }} diff --git a/deploy/k8s/archived/helm/webmvc/templates/deployment.yaml b/deploy/k8s/archived/helm/webmvc/templates/deployment.yaml deleted file mode 100644 index 2889dc757..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/deployment.yaml +++ /dev/null @@ -1,75 +0,0 @@ -{{- $name := include "webmvc.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "webmvc.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "webmvc.name" . }} - chart: {{ template "webmvc.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "webmvc.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "webmvc.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/webmvc/templates/ingress-dockerk8s.yaml b/deploy/k8s/archived/helm/webmvc/templates/ingress-dockerk8s.yaml deleted file mode 100644 index 72e043039..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/ingress-dockerk8s.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- if .Values.inf.k8s.local -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.mvc }} -{{- $name := include "webmvc.fullname" . -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ $name }}-local - labels: - app: {{ template "webmvc.name" . }} - chart: {{ template "webmvc.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: - rules: - - http: - paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: http - path: {{ $ingressPath }} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webmvc/templates/ingress.yaml b/deploy/k8s/archived/helm/webmvc/templates/ingress.yaml deleted file mode 100644 index 1899f5a18..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/ingress.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -{{- $serviceName := .Values.app.svc.mvc -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "webmvc.fullname" . }} - labels: - app: {{ template "webmvc.name" . }} - chart: {{ template "webmvc.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $serviceName }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/webmvc/templates/service.yaml b/deploy/k8s/archived/helm/webmvc/templates/service.yaml deleted file mode 100644 index 74d87673f..000000000 --- a/deploy/k8s/archived/helm/webmvc/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.mvc }} - labels: - app: {{ template "webmvc.name" . }} - chart: {{ template "webmvc.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "webmvc.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/webmvc/values.yaml b/deploy/k8s/archived/helm/webmvc/values.yaml deleted file mode 100644 index 1f40dbb03..000000000 --- a/deploy/k8s/archived/helm/webmvc/values.yaml +++ /dev/null @@ -1,57 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webmvc - -image: - repository: eshop/webmvc - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: true - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: DPConnectionString - key: webmvc__keystore - - name: PurchaseUrl - key: internalurls__apigwws - - name: ExternalPurchaseUrl - key: urls__apigwws - - name: CallBackUrl - key: urls__mvc - - name: IdentityUrl - key: urls__IdentityUrl - - name: IdentityUrlHC - key: internalurls__identity__hc - - name: SignalrHubUrl - key: urls__apigwws - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' - - name: IsClusterEnv - value: 'True' - diff --git a/deploy/k8s/archived/helm/webshoppingagg/.helmignore b/deploy/k8s/archived/helm/webshoppingagg/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/webshoppingagg/Chart.yaml b/deploy/k8s/archived/helm/webshoppingagg/Chart.yaml deleted file mode 100644 index cd7541025..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: webshoppingagg -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/NOTES.txt b/deploy/k8s/archived/helm/webshoppingagg/templates/NOTES.txt deleted file mode 100644 index f55946f36..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/NOTES.txt +++ /dev/null @@ -1,8 +0,0 @@ -eShop Web Shopping Aggregator installed. ----------------------------------------- - -This API is not directly exposed outside cluster. If need to access it use: - -export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "webshoppingagg.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") -echo "Visit http://127.0.0.1:8080 to use your application" -kubectl port-forward $POD_NAME 8080:80 diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/_helpers.tpl b/deploy/k8s/archived/helm/webshoppingagg/templates/_helpers.tpl deleted file mode 100644 index f13dc791d..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "webshoppingagg.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webshoppingagg.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webshoppingagg.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/_names.tpl b/deploy/k8s/archived/helm/webshoppingagg/templates/_names.tpl deleted file mode 100644 index d44859fea..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/_names.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml b/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml deleted file mode 100644 index b21de5a38..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/configmap.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- $name := include "webshoppingagg.fullname" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "webshoppingagg.name" . }} - chart: {{ template "webshoppingagg.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - webshoppingagg__keystore: {{ .Values.inf.redis.keystore.constr }} - internalurls__basket: http://{{ .Values.app.svc.basket }} - internalurls__catalog: http://{{ .Values.app.svc.catalog }} - internalurls__identity: http://{{ .Values.app.svc.identity }} - internalurls__ordering: http://{{ .Values.app.svc.ordering }} - internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc - internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc - internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - internalurls__grpcBasket: "http://{{ .Values.app.svc.basket }}:{{ .Values.service.grpcPort }}" - internalurls__grpcCatalog: "http://{{ .Values.app.svc.catalog }}:{{ .Values.service.grpcPort }}" - internalurls__grpcOrdering: "http://{{ .Values.app.svc.ordering }}:{{ .Values.service.grpcPort }}" diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/deployment.yaml b/deploy/k8s/archived/helm/webshoppingagg/templates/deployment.yaml deleted file mode 100644 index ab5bfc0c9..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/deployment.yaml +++ /dev/null @@ -1,95 +0,0 @@ -{{- $name := include "webshoppingagg.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "webshoppingagg.fullname" . }} - labels: - app: {{ template "webshoppingagg.name" . }} - chart: {{ template "webshoppingagg.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "webshoppingagg.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "webshoppingagg.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - {{ if .Values.probes -}} - {{- if .Values.probes.liveness -}} - livenessProbe: - httpGet: - port: {{ .Values.probes.liveness.port }} - path: {{ .Values.probes.liveness.path }} - initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.liveness.periodSeconds }} - {{- end -}} - {{- end -}} - {{- if .Values.probes -}} - {{- if .Values.probes.readiness }} - readinessProbe: - httpGet: - port: {{ .Values.probes.readiness.port }} - path: {{ .Values.probes.readiness.path }} - initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }} - periodSeconds: {{ .Values.probes.readiness.periodSeconds }} - timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }} - {{- end -}} - {{- end }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/webshoppingagg/templates/service.yaml b/deploy/k8s/archived/helm/webshoppingagg/templates/service.yaml deleted file mode 100644 index 8f0cb8bd5..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.webshoppingagg }} - labels: - app: {{ template "webshoppingagg.name" . }} - chart: {{ template "webshoppingagg.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "webshoppingagg.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/webshoppingagg/values.yaml b/deploy/k8s/archived/helm/webshoppingagg/values.yaml deleted file mode 100644 index 602dcf93a..000000000 --- a/deploy/k8s/archived/helm/webshoppingagg/values.yaml +++ /dev/null @@ -1,83 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webshoppingagg - -image: - repository: eshop/webshoppingagg - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - grpcPort: 81 - -ingress: - enabled: false - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: urls__basket - key: internalurls__basket - - name: urls__catalog - key: internalurls__catalog - - name: urls__orders - key: internalurls__ordering - - name: urls__identity - key: internalurls__identity - - name: CatalogUrlHC - key: internalurls__catalog__hc - - name: BasketUrlHC - key: internalurls__basket__hc - - name: IdentityUrlHC - key: internalurls__identity__hc - - name: OrderingUrlHC - key: internalurls__ordering__hc - - name: PaymentUrlHC - key: internalurls__payment__hc - - name: urls__grpcBasket - key: internalurls__grpcBasket - - name: urls__grpcCatalog - key: internalurls__grpcCatalog - - name: urls__grpcOrdering - key: internalurls__grpcOrdering - - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: ASPNETCORE_URLS - value: http://0.0.0.0:80 - - name: OrchestratorType - value: 'K8S' - - name: IsClusterEnv - value: 'True' -probes: - liveness: - path: /liveness - initialDelaySeconds: 10 - periodSeconds: 15 - port: 80 - readiness: - path: /hc - timeoutSeconds: 5 - initialDelaySeconds: 90 - periodSeconds: 60 - port: 80 - diff --git a/deploy/k8s/archived/helm/webspa/.helmignore b/deploy/k8s/archived/helm/webspa/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/webspa/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/webspa/Chart.yaml b/deploy/k8s/archived/helm/webspa/Chart.yaml deleted file mode 100644 index c16616489..000000000 --- a/deploy/k8s/archived/helm/webspa/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: webspa -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/webspa/templates/NOTES.txt b/deploy/k8s/archived/helm/webspa/templates/NOTES.txt deleted file mode 100644 index c8e1622db..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop WebSPA installed ----------------------- \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webspa/templates/_helpers.tpl b/deploy/k8s/archived/helm/webspa/templates/_helpers.tpl deleted file mode 100644 index 585f9f001..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "webspa.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webspa.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webspa.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/webspa/templates/_names.tpl b/deploy/k8s/archived/helm/webspa/templates/_names.tpl deleted file mode 100644 index 605e92e7e..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/_names.tpl +++ /dev/null @@ -1,60 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - - - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} - -{{- define "protocol" -}} -{{- if .Values.inf.tls.enabled -}} -{{- printf "%s" "https" -}} -{{- else -}} -{{- printf "%s" "http" -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webspa/templates/configmap.yaml b/deploy/k8s/archived/helm/webspa/templates/configmap.yaml deleted file mode 100644 index 353ff638f..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/configmap.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- $name := include "webspa.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} -{{- $spa := include "url-of" (list .Values.app.ingress.entries.spa .) -}} -{{- $mongo := include "mongo-name" . -}} -{{- $protocol := include "protocol" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "webspa.name" . }} - chart: {{ template "webspa.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" - webspa__keystore: {{ .Values.inf.redis.keystore.constr }} - internalurls__apigwws: http://{{ .Values.app.svc.webshoppingapigw }} - internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - urls__apigwws: {{ $protocol }}://{{ $webshoppingapigw }} - urls__spa: {{ $protocol }}://{{ $spa }} - urls__IdentityUrl: {{ $protocol }}://{{ $identity }} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webspa/templates/deployment.yaml b/deploy/k8s/archived/helm/webspa/templates/deployment.yaml deleted file mode 100644 index 20dc696bf..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/deployment.yaml +++ /dev/null @@ -1,75 +0,0 @@ -{{- $name := include "webspa.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "webspa.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "webspa.name" . }} - chart: {{ template "webspa.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "webspa.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "webspa.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/webspa/templates/ingress.yaml b/deploy/k8s/archived/helm/webspa/templates/ingress.yaml deleted file mode 100644 index 2b9fdd703..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/ingress.yaml +++ /dev/null @@ -1,45 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressPath := include "pathBase" . -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "webspa.fullname" . }} - labels: - app: {{ template "webspa.name" . }} - chart: {{ template "webspa.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $.Values.app.svc.spa }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/webspa/templates/service.yaml b/deploy/k8s/archived/helm/webspa/templates/service.yaml deleted file mode 100644 index 2eab5d02e..000000000 --- a/deploy/k8s/archived/helm/webspa/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.spa }} - labels: - app: {{ template "webspa.name" . }} - chart: {{ template "webspa.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "webspa.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/webspa/values.yaml b/deploy/k8s/archived/helm/webspa/values.yaml deleted file mode 100644 index 08e148111..000000000 --- a/deploy/k8s/archived/helm/webspa/values.yaml +++ /dev/null @@ -1,57 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: / - -image: - repository: eshop/webspa - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: true - annotations: {} - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: DPConnectionString - key: webspa__keystore - - name: PurchaseUrl - key: urls__apigwws - - name: CallBackUrl - key: urls__spa - - name: IdentityUrl - key: urls__IdentityUrl - - name: IdentityUrlHC - key: internalurls__identity__hc - - name: SignalrHubUrl - key: urls__apigwws - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: ASPNETCORE_URLS - value: http://0.0.0.0:80 - - name: OrchestratorType - value: 'K8S' - - name: IsClusterEnv - value: 'True' - diff --git a/deploy/k8s/archived/helm/webstatus/.helmignore b/deploy/k8s/archived/helm/webstatus/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/deploy/k8s/archived/helm/webstatus/.helmignore +++ /dev/null @@ -1,21 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/deploy/k8s/archived/helm/webstatus/Chart.yaml b/deploy/k8s/archived/helm/webstatus/Chart.yaml deleted file mode 100644 index 9ee2783f4..000000000 --- a/deploy/k8s/archived/helm/webstatus/Chart.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -appVersion: "1.0" -description: A Helm chart for Kubernetes -name: webstatus -version: 0.1.0 diff --git a/deploy/k8s/archived/helm/webstatus/templates/NOTES.txt b/deploy/k8s/archived/helm/webstatus/templates/NOTES.txt deleted file mode 100644 index 5d9d4570d..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/NOTES.txt +++ /dev/null @@ -1,2 +0,0 @@ -eShop WebStatus installed. --------------------------- \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webstatus/templates/_helpers.tpl b/deploy/k8s/archived/helm/webstatus/templates/_helpers.tpl deleted file mode 100644 index 65b290af7..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/_helpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "webstatus.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "webstatus.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "webstatus.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/deploy/k8s/archived/helm/webstatus/templates/_names.tpl b/deploy/k8s/archived/helm/webstatus/templates/_names.tpl deleted file mode 100644 index 49455d135..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/_names.tpl +++ /dev/null @@ -1,50 +0,0 @@ -{{- define "suffix-name" -}} -{{- if .Values.app.name -}} -{{- .Values.app.name -}} -{{- else -}} -{{- .Release.Name -}} -{{- end -}} -{{- end -}} - -{{- define "sql-name" -}} -{{- if .Values.inf.sql.host -}} -{{- .Values.inf.sql.host -}} -{{- else -}} -{{- printf "%s" "sql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "mongo-name" -}} -{{- if .Values.inf.mongo.host -}} -{{- .Values.inf.mongo.host -}} -{{- else -}} -{{- printf "%s" "nosql-data" -}} -{{- end -}} -{{- end -}} - -{{- define "url-of" -}} -{{- $name := first .}} -{{- $ctx := last .}} -{{- if eq $name "" -}} -{{- $ctx.Values.inf.k8s.dns -}} -{{- else -}} -{{- printf "%s/%s" $ctx.Values.inf.k8s.dns $name -}} {{/*Value is just / */}} -{{- end -}} -{{- end -}} - -{{- define "pathBase" -}} -{{- if .Values.inf.k8s.suffix -}} -{{- $suffix := include "suffix-name" . -}} -{{- printf "%s-%s" .Values.pathBase $suffix -}} -{{- else -}} -{{- .Values.pathBase -}} -{{- end -}} -{{- end -}} - -{{- define "fqdn-image" -}} -{{- if .Values.inf.registry -}} -{{- printf "%s/%s" .Values.inf.registry.server .Values.image.repository -}} -{{- else -}} -{{- .Values.image.repository -}} -{{- end -}} -{{- end -}} \ No newline at end of file diff --git a/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml b/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml deleted file mode 100644 index b53864602..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/configmap.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- $name := include "webstatus.fullname" . -}} -{{- $identity := include "url-of" (list .Values.app.ingress.entries.identity .) -}} -{{- $webshoppingapigw := include "url-of" (list .Values.app.ingress.entries.webshoppingapigw .) -}} -{{- $mvc := include "url-of" (list .Values.app.ingress.entries.mvc .) -}} -{{- $mongo := include "mongo-name" . -}} - -apiVersion: v1 -kind: ConfigMap -metadata: - name: "cfg-{{ $name }}" - labels: - app: {{ template "webstatus.name" . }} - chart: {{ template "webstatus.chart" .}} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -data: - all__InstrumentationKey: "{{ .Values.inf.appinsights.key }}" - all__UseAzureServiceBus: "{{ .Values.inf.eventbus.useAzure }}" - all_EnableLoadTest: "{{ .Values.inf.misc.useLoadTest }}" - webstatus__keystore: {{ .Values.inf.redis.keystore.constr }} - name__mvc__hc: WebMVC HTTP Check - internalurls__mvc__hc: http://{{ .Values.app.svc.mvc }}/hc - name__spa__hc: WebSPA HTTP Check - internalurls__spa__hc: http://{{ .Values.app.svc.spa }}/hc - name__apigwws__hc: Web Shopping API GW HTTP Check - internalurls__apigwws__hc: http://{{ .Values.app.svc.webshoppingapigw }}:8001/ready - name__apigwms__hc: Mobile Shopping API GW HTTP Check - internalurls__apigwms__hc: http://{{ .Values.app.svc.mobileshoppingapigw }}:8001/ready - name__apigwwsagg__hc: Web Shopping Aggregator GW HTTP Check - internalurls__apigwwsagg__hc: http://{{ .Values.app.svc.webshoppingagg }}/hc - name__apigwmsagg__hc: Mobile Shopping Aggregator HTTP Check - internalurls__apigwmsagg__hc: http://{{ .Values.app.svc.mobileshoppingagg }}/hc - name__ordering__hc: Ordering HTTP Check - internalurls__ordering__hc: http://{{ .Values.app.svc.ordering }}/hc - name__orderingbackground__hc: Ordering HTTP Background Check - internalurls__orderingbackground__hc: http://{{ .Values.app.svc.orderingbackgroundtasks }}/hc - name__basket__hc: Basket HTTP Check - internalurls__basket__hc: http://{{ .Values.app.svc.basket }}/hc - name__catalog__hc: Catalog HTTP Check - internalurls__catalog__hc: http://{{ .Values.app.svc.catalog }}/hc - name__identity__hc: Identity HTTP Check - internalurls__identity__hc: http://{{ .Values.app.svc.identity }}/hc - name__payment__hc: Payment HTTP Check - internalurls__payment__hc: http://{{ .Values.app.svc.payment }}/hc - name__signalrhub__hc: Ordering SignalR Hub HTTP Check - internalurls__signalrhub__hc: http://{{ .Values.app.svc.orderingsignalrhub }}/hc diff --git a/deploy/k8s/archived/helm/webstatus/templates/deployment.yaml b/deploy/k8s/archived/helm/webstatus/templates/deployment.yaml deleted file mode 100644 index 70b953577..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/deployment.yaml +++ /dev/null @@ -1,75 +0,0 @@ -{{- $name := include "webstatus.fullname" . -}} -{{- $cfgname := printf "%s-%s" "cfg" $name -}} -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - name: {{ template "webstatus.fullname" . }} - labels: - ufo: {{ $cfgname}} - app: {{ template "webstatus.name" . }} - chart: {{ template "webstatus.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - replicas: {{ .Values.replicaCount }} - selector: - matchLabels: - app: {{ template "webstatus.name" . }} - release: {{ .Release.Name }} - template: - metadata: - labels: - app: {{ template "webstatus.name" . }} - release: {{ .Release.Name }} - {{ if .Values.inf.mesh.enabled -}} - annotations: - linkerd.io/inject: enabled - {{- end }} - spec: - {{ if .Values.inf.registry -}} - imagePullSecrets: - - name: {{ .Values.inf.registry.secretName }} - {{- end }} - containers: - - name: {{ .Chart.Name }} - image: "{{ template "fqdn-image" . }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - env: - - name: PATH_BASE - value: {{ include "pathBase" . }} - - name: k8sname - value: {{ .Values.clusterName }} - {{- if .Values.env.values -}} - {{- range .Values.env.values }} - - name: {{ .name }} - value: {{ .value | quote }} - {{- end -}} - {{- end -}} - {{- if .Values.env.configmap -}} - {{- range .Values.env.configmap }} - - name: {{ .name }} - valueFrom: - configMapKeyRef: - name: {{ $cfgname }} - key: {{ .key }} - {{- end -}} - {{- end }} - ports: - - name: http - containerPort: 80 - protocol: TCP - resources: -{{ toYaml .Values.resources | indent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.affinity }} - affinity: -{{ toYaml . | indent 8 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: -{{ toYaml . | indent 8 }} - {{- end }} - diff --git a/deploy/k8s/archived/helm/webstatus/templates/ingress.yaml b/deploy/k8s/archived/helm/webstatus/templates/ingress.yaml deleted file mode 100644 index 9902b86b5..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/ingress.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "webstatus.fullname" . -}} -{{- $ingressPath := include "pathBase" . -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "webstatus.fullname" . }} - labels: - app: {{ template "webstatus.name" . }} - chart: {{ template "webstatus.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -{{- with .Values.ingress.annotations }} - annotations: -{{ toYaml . | indent 4 }} -{{- end }} -{{- if and .Values.inf.tls.enabled .Values.inf.tls.issuer }} - cert-manager.io/issuer: {{ .Values.inf.tls.issuer }} -{{- end }} -{{- if .Values.inf.mesh.enabled }} -{{- with .Values.ingress.mesh.annotations }} -{{ toYaml . | indent 4 }} -{{- end }} -{{- end }} -spec: -{{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} -{{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ . }} - http: - paths: - - path: {{ $ingressPath }} - backend: - serviceName: {{ $.Values.app.svc.status }} - servicePort: http - {{- end }} -{{- end }} diff --git a/deploy/k8s/archived/helm/webstatus/templates/service.yaml b/deploy/k8s/archived/helm/webstatus/templates/service.yaml deleted file mode 100644 index 37fff50c6..000000000 --- a/deploy/k8s/archived/helm/webstatus/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.app.svc.status }} - labels: - app: {{ template "webstatus.name" . }} - chart: {{ template "webstatus.chart" . }} - release: {{ .Release.Name }} - heritage: {{ .Release.Service }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ template "webstatus.name" . }} - release: {{ .Release.Name }} diff --git a/deploy/k8s/archived/helm/webstatus/values.yaml b/deploy/k8s/archived/helm/webstatus/values.yaml deleted file mode 100644 index 1ce23fec3..000000000 --- a/deploy/k8s/archived/helm/webstatus/values.yaml +++ /dev/null @@ -1,87 +0,0 @@ -replicaCount: 1 -clusterName: eshop-aks -pathBase: /webstatus - -image: - repository: eshop/webstatus - tag: latest - pullPolicy: IfNotPresent - -service: - type: ClusterIP - port: 80 - -ingress: - enabled: true - annotations: { - - } - tls: [] - -resources: {} - - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -# env defines the environment variables that will be declared in the pod -env: - urls: - # configmap declares variables which value is taken from the config map defined in template configmap.yaml (name is name of var and key the key in configmap). - configmap: - - name: ApplicationInsights__InstrumentationKey - key: all__InstrumentationKey - - name: HealthChecks-UI__HealthChecks__0__Name - key: name__mvc__hc - - name: HealthChecks-UI__HealthChecks__0__Uri - key: internalurls__mvc__hc - - name: HealthChecks-UI__HealthChecks__1__Name - key: name__spa__hc - - name: HealthChecks-UI__HealthChecks__1__Uri - key: internalurls__spa__hc - - name: HealthChecks-UI__HealthChecks__2__Name - key: name__apigwwsagg__hc - - name: HealthChecks-UI__HealthChecks__2__Uri - key: internalurls__apigwwsagg__hc - - name: HealthChecks-UI__HealthChecks__3__Name - key: name__apigwmsagg__hc - - name: HealthChecks-UI__HealthChecks__3__Uri - key: internalurls__apigwmsagg__hc - - name: HealthChecks-UI__HealthChecks__4__Name - key: name__ordering__hc - - name: HealthChecks-UI__HealthChecks__4__Uri - key: internalurls__ordering__hc - - name: HealthChecks-UI__HealthChecks__5__Name - key: name__basket__hc - - name: HealthChecks-UI__HealthChecks__5__Uri - key: internalurls__basket__hc - - name: HealthChecks-UI__HealthChecks__6__Name - key: name__catalog__hc - - name: HealthChecks-UI__HealthChecks__6__Uri - key: internalurls__catalog__hc - - name: HealthChecks-UI__HealthChecks__7__Name - key: name__identity__hc - - name: HealthChecks-UI__HealthChecks__7__Uri - key: internalurls__identity__hc - - name: HealthChecks-UI__HealthChecks__8__Name - key: name__payment__hc - - name: HealthChecks-UI__HealthChecks__8__Uri - key: internalurls__payment__hc - - name: HealthChecks-UI__HealthChecks__9__Name - key: name__signalrhub__hc - - name: HealthChecks-UI__HealthChecks__9__Uri - key: internalurls__signalrhub__hc - - name: HealthChecks-UI__HealthChecks__10__Name - key: name__orderingbackground__hc - - name: HealthChecks-UI__HealthChecks__10__Uri - key: internalurls__orderingbackground__hc - - # values define environment variables with a fixed value (no configmap involved) (name is name of var, and value is its value) - values: - - name: ASPNETCORE_ENVIRONMENT - value: Development - - name: OrchestratorType - value: 'K8S' diff --git a/deploy/k8s/archived/linkerd/basket-api-sp.yaml b/deploy/k8s/archived/linkerd/basket-api-sp.yaml deleted file mode 100644 index 6b23bdb9f..000000000 --- a/deploy/k8s/archived/linkerd/basket-api-sp.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: linkerd.io/v1alpha2 -kind: ServiceProfile -metadata: - creationTimestamp: null - name: basket-api.default.svc.cluster.local - namespace: default -spec: - routes: - - condition: - method: GET - pathRegex: /basket-api/api/v1/basket/[^/]* - name: GET Basket {id} - isRetryable: true - - condition: - method: GET - pathRegex: /hc - name: GET /hc - isRetryable: false - - condition: - method: GET - pathRegex: /liveness - name: GET /liveness - isRetryable: false - - condition: - method: POST - pathRegex: /BasketApi\.Basket/GetBasketById - name: POST /BasketApi.Basket/GetBasketById - isRetryable: true - - condition: - method: POST - pathRegex: /BasketApi\.Basket/UpdateBasket - name: POST /BasketApi.Basket/UpdateBasket - isRetryable: true - - condition: - method: POST - pathRegex: /basket-api/api/v1/basket/checkout - name: POST /v1/basket/checkout - isRetryable: true - retryBudget: - retryRatio: 0.2 - minRetriesPerSecond: 10 - ttl: 10s \ No newline at end of file diff --git a/deploy/k8s/archived/linkerd/catalog-api-sp.yaml b/deploy/k8s/archived/linkerd/catalog-api-sp.yaml deleted file mode 100644 index 6e9afa472..000000000 --- a/deploy/k8s/archived/linkerd/catalog-api-sp.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: linkerd.io/v1alpha2 -kind: ServiceProfile -metadata: - creationTimestamp: null - name: catalog-api.default.svc.cluster.local - namespace: default -spec: - routes: - - condition: - method: GET - pathRegex: /catalog-api/api/v1/catalog/catalogbrands - name: GET /v1/catalog/catalogbrands - isRetryable: true - - condition: - method: GET - pathRegex: /catalog-api/api/v1/catalog/catalogtypes - name: GET /v1/catalog/catalogtypes - isRetryable: true - - condition: - method: GET - pathRegex: /catalog-api/api/v1/catalog/items - name: GET /v1/catalog/items - isRetryable: true - - condition: - method: GET - pathRegex: /api/v1/catalog/items/[^/]*/pic/ - name: GET /v1/catalog/items/{id}/pic/ - isRetryable: false - - condition: - method: GET - pathRegex: /hc - name: GET /hc - isRetryable: false - - condition: - method: GET - pathRegex: /liveness - isRetryable: false - name: GET /liveness - - condition: - method: POST - pathRegex: /CatalogApi\.Catalog/GetItemsByIds - name: POST /CatalogApi.Catalog/GetItemsByIds - isRetryable: true - retryBudget: - retryRatio: 0.2 - minRetriesPerSecond: 10 - ttl: 10s \ No newline at end of file diff --git a/deploy/k8s/archived/nginx-ingress/local-cm.yaml b/deploy/k8s/archived/nginx-ingress/local-cm.yaml deleted file mode 100644 index 02906afc1..000000000 --- a/deploy/k8s/archived/nginx-ingress/local-cm.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx - name: nginx-configuration - namespace: ingress-nginx -data: - proxy-buffer-size: "128k" - proxy-buffers: "4 256k" \ No newline at end of file diff --git a/deploy/k8s/archived/nginx-ingress/local-dockerk8s/identityapi-cm-fix.yaml b/deploy/k8s/archived/nginx-ingress/local-dockerk8s/identityapi-cm-fix.yaml deleted file mode 100644 index 3a3fcf5a5..000000000 --- a/deploy/k8s/archived/nginx-ingress/local-dockerk8s/identityapi-cm-fix.yaml +++ /dev/null @@ -1,3 +0,0 @@ -data: - mvc_e: http://10.0.75.1/webmvc - \ No newline at end of file diff --git a/deploy/k8s/archived/nginx-ingress/local-dockerk8s/mvc-cm-fix.yaml b/deploy/k8s/archived/nginx-ingress/local-dockerk8s/mvc-cm-fix.yaml deleted file mode 100644 index 1475deec1..000000000 --- a/deploy/k8s/archived/nginx-ingress/local-dockerk8s/mvc-cm-fix.yaml +++ /dev/null @@ -1,3 +0,0 @@ -data: - urls__IdentityUrl: http://10.0.75.1/identity - urls__mvc: http://10.0.75.1/webmvc diff --git a/deploy/k8s/archived/nginx-ingress/local-dockerk8s/mvc-fix.yaml b/deploy/k8s/archived/nginx-ingress/local-dockerk8s/mvc-fix.yaml deleted file mode 100644 index b9ecd4cba..000000000 --- a/deploy/k8s/archived/nginx-ingress/local-dockerk8s/mvc-fix.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - annotations: - ingress.kubernetes.io/ssl-redirect: "false" - kubernetes.io/ingress.class: nginx - nginx.ingress.kubernetes.io/ssl-redirect: "false" - labels: - app: webmvc - name: eshop-webmvc-loopback - namespace: default -spec: - rules: - - http: - paths: - - backend: - serviceName: webmvc - servicePort: http - path: /webmvc ---- -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - annotations: - ingress.kubernetes.io/ssl-redirect: "false" - kubernetes.io/ingress.class: nginx - nginx.ingress.kubernetes.io/ssl-redirect: "false" - labels: - app: identity-api - name: eshop-identity-api-loopback - namespace: default -spec: - rules: - - http: - paths: - - backend: - serviceName: identity - servicePort: http - path: /identity \ No newline at end of file diff --git a/deploy/k8s/archived/nginx-ingress/local-svc.yaml b/deploy/k8s/archived/nginx-ingress/local-svc.yaml deleted file mode 100644 index 945441ab8..000000000 --- a/deploy/k8s/archived/nginx-ingress/local-svc.yaml +++ /dev/null @@ -1,21 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: ingress-nginx - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -spec: - externalTrafficPolicy: Local - type: LoadBalancer - selector: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx - ports: - - name: http - port: 80 - targetPort: http - - name: https - port: 443 - targetPort: https \ No newline at end of file diff --git a/deploy/k8s/archived/nginx-ingress/mandatory.yaml b/deploy/k8s/archived/nginx-ingress/mandatory.yaml deleted file mode 100644 index 56b1cc3b5..000000000 --- a/deploy/k8s/archived/nginx-ingress/mandatory.yaml +++ /dev/null @@ -1,238 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: ingress-nginx - ---- - -kind: ConfigMap -apiVersion: v1 -metadata: - name: nginx-configuration - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx - ---- - -apiVersion: v1 -kind: ServiceAccount -metadata: - name: nginx-ingress-serviceaccount - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx - ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - name: nginx-ingress-clusterrole - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -rules: - - apiGroups: - - "" - resources: - - configmaps - - endpoints - - nodes - - pods - - secrets - verbs: - - list - - watch - - apiGroups: - - "" - resources: - - nodes - verbs: - - get - - apiGroups: - - "" - resources: - - services - verbs: - - get - - list - - watch - - apiGroups: - - "extensions" - resources: - - ingresses - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - - apiGroups: - - "extensions" - resources: - - ingresses/status - verbs: - - update - ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: Role -metadata: - name: nginx-ingress-role - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -rules: - - apiGroups: - - "" - resources: - - configmaps - - pods - - secrets - - namespaces - verbs: - - get - - apiGroups: - - "" - resources: - - configmaps - resourceNames: - # Defaults to "-" - # Here: "-" - # This has to be adapted if you change either parameter - # when launching the nginx-ingress-controller. - - "ingress-controller-leader-nginx" - verbs: - - get - - update - - apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - apiGroups: - - "" - resources: - - endpoints - verbs: - - get - ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: RoleBinding -metadata: - name: nginx-ingress-role-nisa-binding - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: nginx-ingress-role -subjects: - - kind: ServiceAccount - name: nginx-ingress-serviceaccount - namespace: ingress-nginx - ---- -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - name: nginx-ingress-clusterrole-nisa-binding - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: nginx-ingress-clusterrole -subjects: - - kind: ServiceAccount - name: nginx-ingress-serviceaccount - namespace: ingress-nginx - ---- - -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: nginx-ingress-controller - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx - template: - metadata: - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx - annotations: - prometheus.io/port: "10254" - prometheus.io/scrape: "true" - spec: - serviceAccountName: nginx-ingress-serviceaccount - containers: - - name: nginx-ingress-controller - image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.20.0 - args: - - /nginx-ingress-controller - - --configmap=$(POD_NAMESPACE)/nginx-configuration - - --publish-service=$(POD_NAMESPACE)/ingress-nginx - - --annotations-prefix=nginx.ingress.kubernetes.io - securityContext: - capabilities: - drop: - - ALL - add: - - NET_BIND_SERVICE - # www-data -> 33 - runAsUser: 33 - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - ports: - - name: http - containerPort: 80 - - name: https - containerPort: 443 - livenessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10254 - scheme: HTTP - initialDelaySeconds: 10 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - httpGet: - path: /healthz - port: 10254 - scheme: HTTP - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 diff --git a/deploy/k8s/archived/nginx-ingress/service-nodeport.yaml b/deploy/k8s/archived/nginx-ingress/service-nodeport.yaml deleted file mode 100644 index dd82ed3ed..000000000 --- a/deploy/k8s/archived/nginx-ingress/service-nodeport.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: ingress-nginx - namespace: ingress-nginx - labels: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx -spec: - type: NodePort - ports: - - name: http - port: 80 - targetPort: 80 - protocol: TCP - - name: https - port: 443 - targetPort: 443 - protocol: TCP - selector: - app.kubernetes.io/name: ingress-nginx - app.kubernetes.io/part-of: ingress-nginx diff --git a/deploy/k8s/archived/nodeports/rabbitmq-admin.yaml b/deploy/k8s/archived/nodeports/rabbitmq-admin.yaml deleted file mode 100644 index 30d2facf1..000000000 --- a/deploy/k8s/archived/nodeports/rabbitmq-admin.yaml +++ /dev/null @@ -1,12 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: rabbitmq-admin -spec: - type: NodePort - selector: - app: rabbitmq - ports: - - port: 15672 - nodePort: 31672 - name: rabbitmq-port diff --git a/deploy/k8s/archived/nodeports/sql-service.yaml b/deploy/k8s/archived/nodeports/sql-service.yaml deleted file mode 100644 index 7b0233b68..000000000 --- a/deploy/k8s/archived/nodeports/sql-service.yaml +++ /dev/null @@ -1,12 +0,0 @@ -kind: Service -apiVersion: v1 -metadata: - name: sql-service -spec: - type: NodePort - selector: - app: sql-data - ports: - - port: 1433 - nodePort: 31433 - name: sql-port diff --git a/deploy/k8s/create-aks.ps1 b/deploy/k8s/create-aks.ps1 index 327f5fd6b..3d7145ee8 100644 --- a/deploy/k8s/create-aks.ps1 +++ b/deploy/k8s/create-aks.ps1 @@ -30,7 +30,7 @@ Write-Host "Creating AKS $resourceGroupName/$serviceName" -ForegroundColor Yello az aks create --resource-group=$resourceGroupName --name=$serviceName --dns-name-prefix=$dnsNamePrefix --generate-ssh-keys --node-count=$nodeCount --node-vm-size=$nodeVMSize --vm-set-type $vmSetType if ($enableHttpApplicationAddon) { - Write-Host "Enabling Http Applciation Routing in AKS $serviceName" -ForegroundColor Yellow + Write-Host "Enabling Http Application Routing in AKS $serviceName" -ForegroundColor Yellow az aks enable-addons --resource-group $resourceGroupName --name $serviceName --addons http_application_routing } diff --git a/deploy/k8s/helm/apigwms/envoy.yaml b/deploy/k8s/helm/apigwms/envoy.yaml index 1ae8c45a1..07deca932 100644 --- a/deploy/k8s/helm/apigwms/envoy.yaml +++ b/deploy/k8s/helm/apigwms/envoy.yaml @@ -9,19 +9,20 @@ static_resources: - address: socket_address: address: 0.0.0.0 - port_value: 80 + port_value: 8080 filter_chains: - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http + codec_type: AUTO route_config: name: eshop_backend_route virtual_hosts: - name: eshop_backend domains: - - "*" + - ["*"] routes: - name: "c-short" match: @@ -77,63 +78,70 @@ static_resources: prefix_rewrite: "/" cluster: shoppingagg http_filters: - - name: envoy.router - access_log: - - name: envoy.file_access_log - filter: - not_health_check_filter: {} - config: - json_format: - time: "%START_TIME%" - protocol: "%PROTOCOL%" - duration: "%DURATION%" - request_method: "%REQ(:METHOD)%" - request_host: "%REQ(HOST)%" - path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" - response_flags: "%RESPONSE_FLAGS%" - route_name: "%ROUTE_NAME%" - upstream_host: "%UPSTREAM_HOST%" - upstream_cluster: "%UPSTREAM_CLUSTER%" - upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%" - path: "/tmp/access.log" + - name: envoy.filters.http.router clusters: - name: shoppingagg connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: webshoppingagg - port_value: 80 + load_assignment: + cluster_name: shoppingagg + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: webshoppingagg + port_value: 80 - name: catalog connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: catalog-api - port_value: 80 + load_assignment: + cluster_name: catalog + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: catalog-api + port_value: 80 - name: basket connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: basket-api - port_value: 80 + load_assignment: + cluster_name: basket + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: basket-api + port_value: 80 - name: ordering connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: ordering-api - port_value: 80 + load_assignment: + cluster_name: ordering + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ordering-api + port_value: 80 - name: signalr-hub connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: ordering-signalrhub - port_value: 80 + load_assignment: + cluster_name: signalr-hub + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ordering-signalrhub + port_value: 80 diff --git a/deploy/k8s/helm/apigwms/templates/deployment.yaml b/deploy/k8s/helm/apigwms/templates/deployment.yaml index c62751f1c..2fb42f4fb 100644 --- a/deploy/k8s/helm/apigwms/templates/deployment.yaml +++ b/deploy/k8s/helm/apigwms/templates/deployment.yaml @@ -27,6 +27,10 @@ spec: linkerd.io/inject: enabled {{- end }} spec: + securityContext: + runAsUser: 2000 + runAsGroup: 3000 + fsGroup: 2000 {{ if .Values.inf.registry -}} imagePullSecrets: - name: {{ .Values.inf.registry.secretName }} @@ -88,7 +92,7 @@ spec: {{- end }} ports: - name: http - containerPort: 80 + containerPort: 8080 protocol: TCP - name: admin containerPort: 8001 diff --git a/deploy/k8s/helm/apigwms/templates/ingress.yaml b/deploy/k8s/helm/apigwms/templates/ingress.yaml index bc0c6d05b..528296261 100644 --- a/deploy/k8s/helm/apigwms/templates/ingress.yaml +++ b/deploy/k8s/helm/apigwms/templates/ingress.yaml @@ -2,7 +2,7 @@ {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.mobileshoppingapigw -}} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "apigwms.fullname" . }} @@ -39,9 +39,12 @@ spec: - host: {{ . }} http: paths: - - path: {{ $ingressPath }} + - path: {{ $ingressPath }}(/|$)(.*) + pathType: Prefix backend: - serviceName: {{ $serviceName }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/apigwms/values.yaml b/deploy/k8s/helm/apigwms/values.yaml index 4a92d85e9..0e7ff5a09 100644 --- a/deploy/k8s/helm/apigwms/values.yaml +++ b/deploy/k8s/helm/apigwms/values.yaml @@ -4,7 +4,7 @@ pathBase: /mobileshoppingapigw image: repository: envoyproxy/envoy - tag: v1.11.1 + tag: v1.21.0 service: type: ClusterIP @@ -14,8 +14,9 @@ service: ingress: enabled: true annotations: - nginx.ingress.kubernetes.io/rewrite-target: "/" - ingress.kubernetes.io/rewrite-target: "/" + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/rewrite-target: /$2 + nginx.ingress.kubernetes.io/use-regex: "true" tls: [] resources: {} diff --git a/deploy/k8s/helm/apigwws/envoy.yaml b/deploy/k8s/helm/apigwws/envoy.yaml index 688fb740c..939649e60 100644 --- a/deploy/k8s/helm/apigwws/envoy.yaml +++ b/deploy/k8s/helm/apigwws/envoy.yaml @@ -9,19 +9,20 @@ static_resources: - address: socket_address: address: 0.0.0.0 - port_value: 80 + port_value: 8080 filter_chains: - filters: - - name: envoy.http_connection_manager - config: - codec_type: auto + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http + codec_type: AUTO route_config: name: eshop_backend_route virtual_hosts: - name: eshop_backend domains: - - "*" + - ["*"] routes: - name: "c-short" match: @@ -80,63 +81,70 @@ static_resources: prefix_rewrite: "/" cluster: shoppingagg http_filters: - - name: envoy.router - access_log: - - name: envoy.file_access_log - filter: - not_health_check_filter: {} - config: - json_format: - time: "%START_TIME%" - protocol: "%PROTOCOL%" - duration: "%DURATION%" - request_method: "%REQ(:METHOD)%" - request_host: "%REQ(HOST)%" - path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%" - response_flags: "%RESPONSE_FLAGS%" - route_name: "%ROUTE_NAME%" - upstream_host: "%UPSTREAM_HOST%" - upstream_cluster: "%UPSTREAM_CLUSTER%" - upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%" - path: "/tmp/access.log" + - name: envoy.filters.http.router clusters: - name: shoppingagg connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: webshoppingagg - port_value: 80 + load_assignment: + cluster_name: shoppingagg + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: webshoppingagg + port_value: 80 - name: catalog connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: catalog-api - port_value: 80 + load_assignment: + cluster_name: catalog + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: catalog-api + port_value: 80 - name: basket connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: basket-api - port_value: 80 + load_assignment: + cluster_name: basket + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: basket-api + port_value: 80 - name: ordering connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: ordering-api - port_value: 80 + load_assignment: + cluster_name: ordering + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ordering-api + port_value: 80 - name: signalr-hub connect_timeout: 0.25s type: strict_dns lb_policy: round_robin - hosts: - - socket_address: - address: ordering-signalrhub - port_value: 80 + load_assignment: + cluster_name: signalr-hub + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: ordering-signalrhub + port_value: 80 \ No newline at end of file diff --git a/deploy/k8s/helm/apigwws/templates/deployment.yaml b/deploy/k8s/helm/apigwws/templates/deployment.yaml index bbe7fedf8..3bbcec274 100644 --- a/deploy/k8s/helm/apigwws/templates/deployment.yaml +++ b/deploy/k8s/helm/apigwws/templates/deployment.yaml @@ -26,6 +26,10 @@ spec: linkerd.io/inject: enabled {{- end }} spec: + securityContext: + runAsUser: 2000 + runAsGroup: 3000 + fsGroup: 2000 {{ if .Values.inf.registry -}} imagePullSecrets: - name: {{ .Values.inf.registry.secretName }} @@ -87,7 +91,7 @@ spec: {{- end }} ports: - name: http - containerPort: 80 + containerPort: 8080 protocol: TCP - name: admin containerPort: 8001 diff --git a/deploy/k8s/helm/apigwws/templates/ingress.yaml b/deploy/k8s/helm/apigwws/templates/ingress.yaml index 945038081..0e937067d 100644 --- a/deploy/k8s/helm/apigwws/templates/ingress.yaml +++ b/deploy/k8s/helm/apigwws/templates/ingress.yaml @@ -1,7 +1,7 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.webshoppingapigw -}} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "apigwws.fullname" . }} @@ -38,9 +38,12 @@ spec: - host: {{ . }} http: paths: - - path: {{ $ingressPath }} + - path: {{ $ingressPath }}(/|$)(.*) + pathType: Prefix backend: - serviceName: {{ $serviceName }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/apigwws/values.yaml b/deploy/k8s/helm/apigwws/values.yaml index fb1182dac..9ab7743d5 100644 --- a/deploy/k8s/helm/apigwws/values.yaml +++ b/deploy/k8s/helm/apigwws/values.yaml @@ -4,7 +4,7 @@ pathBase: /webshoppingapigw image: repository: envoyproxy/envoy - tag: v1.11.1 + tag: v1.21.0 service: type: ClusterIP @@ -14,8 +14,9 @@ service: ingress: enabled: true annotations: - nginx.ingress.kubernetes.io/rewrite-target: "/" - ingress.kubernetes.io/rewrite-target: "/" + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/rewrite-target: /$2 + nginx.ingress.kubernetes.io/use-regex: "true" tls: [] resources: {} diff --git a/deploy/k8s/helm/deploy-all.sh b/deploy/k8s/helm/deploy-all.sh index 4b4c8eafd..704dffe92 100644 --- a/deploy/k8s/helm/deploy-all.sh +++ b/deploy/k8s/helm/deploy-all.sh @@ -43,6 +43,10 @@ Parameters: The Docker username used to logon to the custom registry, supplied using the -r parameter. --use-local-k8s Deploy to a locally installed Kubernetes (default: false). + --use-mesh + Use Linkerd as service mesh + --image-pull-policy + Image Pull Policy: Always, IfNotPresent, Never (default: Always) It is assumed that the Kubernetes cluster has been granted access to the container registry. If using AKS and ACR see link for more info: @@ -72,6 +76,9 @@ push_images='' skip_infrastructure='' use_local_k8s='' namespace='eshop' +use_mesh='false' +ingressMeshAnnotationsFile='ingress_values_linkerd.yaml' +imagePullPolicy='Always' while [[ $# -gt 0 ]]; do case "$1" in @@ -107,12 +114,21 @@ while [[ $# -gt 0 ]]; do use_local_k8s='yes'; shift ;; --namespace ) namespace="$2"; shift 2;; + --use-mesh ) + use_mesh='true'; shift ;; + --image-pull-policy ) + imagePullPolicy="$2"; shift 2;; *) echo "Unknown option $1" usage; exit 2 ;; esac done +if [[ $imagePullPolicy != "Always" && $imagePullPolicy != "Never" && $imagePullPolicy != "IfNotPresent" ]]; then + echo "--image-pull-policy needs to be a valid value: Always, IfNotPresent, Never" + usage; exit 2; +fi + if [[ $build_solution ]]; then echo "#################### Building $app_name solution ####################" dotnet publish -o obj/Docker/publish ../../eShopOnContainers-ServicesAndWebApps.sln @@ -201,7 +217,7 @@ if [[ $clean ]]; then if [[ -z $(helm ls -q --namespace $namespace) ]]; then echo "No previous releases found" else - helm uninstall $(helm ls -q --namespace $namespace) + helm --namespace $namespace uninstall $(helm ls -q --namespace $namespace) echo "Previous releases deleted" waitsecs=10; while [ $waitsecs -gt 0 ]; do echo -ne "$waitsecs\033[0K\r"; sleep 1; : $((waitsecs--)); done fi @@ -209,24 +225,31 @@ fi echo "#################### Begin $app_name installation using Helm ####################" infras=(sql-data nosql-data rabbitmq keystore-data basket-data) -charts=(eshop-common apigwms apigwws basket-api catalog-api identity-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) +charts=(eshop-common basket-api catalog-api identity-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) +gateways=(apigwms apigwws) if [[ !$skip_infrastructure ]]; then for infra in "${infras[@]}" do echo "Installing infrastructure: $infra" - helm install "$app_name-$infra" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns $infra + helm install "$app_name-$infra" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --values $ingressMeshAnnotationsFile --set app.name=$app_name --set inf.k8s.dns=$dns $infra --set inf.mesh.enabled=$use_mesh done fi for chart in "${charts[@]}" do echo "Installing: $chart" - if [[ $use_custom_registry ]]; then - helm install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --set inf.registry.server=$container_registry --set inf.registry.login=$docker_username --set inf.registry.pwd=$docker_password --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart - elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed - helm install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart + if [[ $use_custom_registry ]]; then + helm install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --set inf.registry.server=$container_registry --set inf.registry.login=$docker_username --set inf.registry.pwd=$docker_password --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingress_values_file --values $ingressMeshAnnotationsFile --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=$imagePullPolicy $chart --set inf.mesh.enabled=$use_mesh + elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed + helm install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --values $ingressMeshAnnotationsFile --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=$imagePullPolicy $chart --set inf.mesh.enabled=$use_mesh fi done -echo "FINISHED: Helm charts installed." +for gw in "${gateways[@]}" +do + echo "Installing gateway: $gw" + helm install "$app_name-$gw" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.pullPolicy=$imagePullPolicy $gw +done + +echo "FINISHED: Helm charts installed." \ No newline at end of file diff --git a/deploy/k8s/archived/helm/deploy-all.sh b/deploy/k8s/helm/deploy-chart.sh old mode 100644 new mode 100755 similarity index 58% rename from deploy/k8s/archived/helm/deploy-all.sh rename to deploy/k8s/helm/deploy-chart.sh index ad76bd54c..4196d5cfe --- a/deploy/k8s/archived/helm/deploy-all.sh +++ b/deploy/k8s/helm/deploy-chart.sh @@ -12,18 +12,14 @@ Parameters: The name of the AKS cluster. Required when the registry (using the -r parameter) is set to "aks". --aks-rg The resource group for the AKS cluster. Required when the registry (using the -r parameter) is set to "aks". - -b | --build-solution - Force a solution build before deployment (default: false). + -c | --chart + The name of the chart to upgrade (or install) -d | --dns | --dns aks Specifies the external DNS/ IP address of the Kubernetes cluster. If 'aks' is set as value, the DNS value is retrieved from the AKS. --aks-name and --aks-rg are needed. When --use-local-k8s is specified the external DNS is automatically set to localhost. -h | --help Displays this help text and exits the script. - --image-build - Build images (default is to not build all images). - --image-push - Upload images to the container registry (default is not pushing to the custom registry) -n | --app-name Specifies the name of the application (default: eshop). --namespace @@ -33,10 +29,7 @@ Parameters: -r | --registry Specifies the container registry to use (required), e.g. myregistry.azurecr.io. --skip-clean - Do not clean the Kubernetes cluster (default is to clean the cluster). - --skip-infrastructure - Do not deploy infrastructure resources (like sql-data, no-sql or redis). - This is useful for production environments where infrastructure is hosted outside the Kubernetes cluster. + Do not clean the Kubernetes helm chart. Default is to clean the chart. -t | --tag The tag used for the newly created docker images. Default: latest. -u | --docker-username @@ -57,30 +50,31 @@ For more information see https://kubernetes.io/docs/tasks/administer-cluster/nam END } +acr_connected='' app_name='eshop' aks_name='' aks_rg='' -build_images='' +chart='' clean='yes' -build_solution='' container_registry='' docker_password='' docker_username='' dns='' image_tag='latest' -push_images='' skip_infrastructure='' use_local_k8s='' namespace='eshop' while [[ $# -gt 0 ]]; do case "$1" in + --acr-connected ) + acr_connected='yes'; shift ;; --aks-name ) aks_name="$2"; shift 2;; --aks-rg ) aks_rg="$2"; shift 2;; - -b | --build-solution ) - build_solution='yes'; shift ;; + -c | --chart ) + chart="$2"; shift 2;; -d | --dns ) dns="$2"; shift 2;; -h | --help ) @@ -113,24 +107,11 @@ while [[ $# -gt 0 ]]; do esac done -if [[ $build_solution ]]; then - echo "#################### Building $app_name solution ####################" - dotnet publish -o obj/Docker/publish ../../eShopOnContainers-ServicesAndWebApps.sln -fi - export TAG=$image_tag -if [[ $build_images ]]; then - echo "#################### Building the $app_name Docker images ####################" - docker-compose -p ../.. -f ../../docker-compose.yml build - - # Remove temporary images - docker rmi $(docker images -qf "dangling=true") -fi - use_custom_registry='' -if [[ -n $container_registry ]]; then +if [[ -n $container_registry ]] && [[ -z $acr_connected ]]; then echo "################ Log into custom registry $container_registry ##################" use_custom_registry='yes' if [[ -z $docker_username ]] || [[ -z $docker_password ]]; then @@ -140,22 +121,6 @@ if [[ -n $container_registry ]]; then docker login -u $docker_username -p $docker_password $container_registry fi -if [[ $push_images ]]; then - echo "#################### Pushing images to the container registry ####################" - services=(basket.api catalog.api identity.api ordering.api payment.api webmvc webspa webstatus) - - if [[ -z "$(docker image ls -q --filter=reference=eshop/$service:$image_tag)" ]]; then - image_tag=linux-$image_tag - fi - - for service in "${services[@]}" - do - echo "Pushing image for service $service..." - docker tag "eshop/$service:$image_tag" "$container_registry/$service:$image_tag" - docker push "$container_registry/$service:$image_tag" - done -fi - ingress_values_file="ingress_values.yaml" if [[ $use_local_k8s ]]; then @@ -196,37 +161,39 @@ if [[ -z $dns ]]; then echo "No DNS specified. Ingress resources will be bound to public IP." fi -if [[ $clean ]]; then - echo "Cleaning previous helm releases..." - if [[ -z $(helm ls -q --namespace $namespace) ]]; then - echo "No previous releases found" - else - helm delete --purge $(helm ls -q --namespace $namespace) - echo "Previous releases deleted" - waitsecs=10; while [ $waitsecs -gt 0 ]; do echo -ne "$waitsecs\033[0K\r"; sleep 1; : $((waitsecs--)); done - fi +previous_install='' +if [[ -z $(helm ls -q --namespace $namespace | grep "$app_name-$chart") ]]; then + echo "No previous release found" +else + previous_install='yes' fi - -echo "#################### Begin $app_name installation using Helm ####################" -infras=(sql-data nosql-data rabbitmq keystore-data basket-data) -charts=(eshop-common apigwms apigwws basket-api catalog-api identity-api mobileshoppingagg ordering-api ordering-backgroundtasks ordering-signalrhub payment-api webmvc webshoppingagg webspa webstatus webhooks-api webhooks-web) - -if [[ !$skip_infrastructure ]]; then - for infra in "${infras[@]}" - do - echo "Installing infrastructure: $infra" - helm install --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --name="$app_name-$infra" $infra - done + +if [[ $clean ]] && [[ $previous_install ]]; then + echo "Cleaning previous helm releases..." + helm uninstall "$app_name-$chart" --namespace $namespace + echo "Previous release deleted" + waitsecs=5; while [ $waitsecs -gt 0 ]; do echo -ne "$waitsecs\033[0K\r"; sleep 1; : $((waitsecs--)); done + previous_install='' fi -for chart in "${charts[@]}" -do - echo "Installing: $chart" - if [[ $use_custom_registry ]]; then - helm install --namespace $namespace --set "ingress.hosts={$dns}" --set inf.registry.server=$container_registry --set inf.registry.login=$docker_username --set inf.registry.pwd=$docker_password --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always --name="$app_name-$chart" $chart - elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed - helm install --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always --name="$app_name-$chart" $chart +echo "#################### Begin $app_name $chart installation using Helm ####################" +if [[ $use_custom_registry ]] || [[ $acr_connected ]]; then + if [[ -z $acr_connected ]]; then + if [[ -z $previous_install ]]; then + helm upgrade --install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --set inf.registry.server=$container_registry --set inf.registry.login=$docker_username --set inf.registry.pwd=$docker_password --set inf.registry.secretName=eshop-docker-scret --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart + else + helm upgrade --install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart fi -done - -echo "FINISHED: Helm charts installed." + elif [[ $chart != "eshop-common" ]]; then + # ACR is already connected, so we don't need username/password + if [[ -z $previous_install ]]; then + helm install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --set inf.registry.server=$container_registry --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart + else + # don't set the image repo since it's already set + helm upgrade "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart + fi + fi +elif [[ $chart != "eshop-common" ]]; then # eshop-common is ignored when no secret must be deployed + helm upgrade --install "$app_name-$chart" --namespace $namespace --set "ingress.hosts={$dns}" --values app.yaml --values inf.yaml --values $ingress_values_file --set app.name=$app_name --set inf.k8s.dns=$dns --set image.tag=$image_tag --set image.pullPolicy=Always $chart +fi +echo "FINISHED: Helm chart installed." \ No newline at end of file diff --git a/deploy/k8s/helm/identity-api/templates/ingress-dockerk8s.yaml b/deploy/k8s/helm/identity-api/templates/ingress-dockerk8s.yaml index b6a8980f2..c8a29400c 100644 --- a/deploy/k8s/helm/identity-api/templates/ingress-dockerk8s.yaml +++ b/deploy/k8s/helm/identity-api/templates/ingress-dockerk8s.yaml @@ -3,7 +3,7 @@ {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.identity }} {{- $name := include "identity-api.fullname" . -}} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ $name }}-local @@ -25,9 +25,12 @@ spec: rules: - http: paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: http - path: {{ $ingressPath }} + - path: {{ $ingressPath }} + pathType: Prefix + backend: + service: + name: {{ $serviceName }} + port: + number: 80 {{- end -}} {{- end -}} \ No newline at end of file diff --git a/deploy/k8s/helm/identity-api/templates/ingress.yaml b/deploy/k8s/helm/identity-api/templates/ingress.yaml index 751636926..468592658 100644 --- a/deploy/k8s/helm/identity-api/templates/ingress.yaml +++ b/deploy/k8s/helm/identity-api/templates/ingress.yaml @@ -1,7 +1,7 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.identity }} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "identity-api.fullname" . }} @@ -39,8 +39,11 @@ spec: http: paths: - path: {{ $ingressPath }} + pathType: Prefix backend: - serviceName: {{ $serviceName }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/webhooks-api/templates/ingress.yaml b/deploy/k8s/helm/webhooks-api/templates/ingress.yaml index c7c096b77..32effa98e 100644 --- a/deploy/k8s/helm/webhooks-api/templates/ingress.yaml +++ b/deploy/k8s/helm/webhooks-api/templates/ingress.yaml @@ -1,7 +1,7 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.webhooks }} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "webhooks-api.fullname" . }} @@ -39,8 +39,11 @@ spec: http: paths: - path: {{ $ingressPath }} + pathType: Prefix backend: - serviceName: {{ $serviceName }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/webhooks-web/templates/ingress.yaml b/deploy/k8s/helm/webhooks-web/templates/ingress.yaml index 1e5df8c45..a2644add1 100644 --- a/deploy/k8s/helm/webhooks-web/templates/ingress.yaml +++ b/deploy/k8s/helm/webhooks-web/templates/ingress.yaml @@ -1,6 +1,8 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} -apiVersion: extensions/v1beta1 +{{- $serviceName := $.Values.app.svc.webhooksweb -}} + +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "webhooks-web.fullname" . }} @@ -38,8 +40,11 @@ spec: http: paths: - path: {{ $ingressPath }} + pathType: Prefix backend: - serviceName: {{ $.Values.app.svc.webhooksweb }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/webmvc/templates/ingress-dockerk8s.yaml b/deploy/k8s/helm/webmvc/templates/ingress-dockerk8s.yaml index 72e043039..074da7e88 100644 --- a/deploy/k8s/helm/webmvc/templates/ingress-dockerk8s.yaml +++ b/deploy/k8s/helm/webmvc/templates/ingress-dockerk8s.yaml @@ -3,7 +3,7 @@ {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.mvc }} {{- $name := include "webmvc.fullname" . -}} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ $name }}-local @@ -25,9 +25,13 @@ spec: rules: - http: paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: http - path: {{ $ingressPath }} + - path: {{ $ingressPath }} + pathType: Prefix + backend: + service: + name: {{ $serviceName }} + port: + number: 80 + {{- end -}} {{- end -}} \ No newline at end of file diff --git a/deploy/k8s/helm/webmvc/templates/ingress.yaml b/deploy/k8s/helm/webmvc/templates/ingress.yaml index 1899f5a18..2e5b49a89 100644 --- a/deploy/k8s/helm/webmvc/templates/ingress.yaml +++ b/deploy/k8s/helm/webmvc/templates/ingress.yaml @@ -1,7 +1,7 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} {{- $serviceName := .Values.app.svc.mvc -}} -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "webmvc.fullname" . }} @@ -39,8 +39,11 @@ spec: http: paths: - path: {{ $ingressPath }} + pathType: Prefix backend: - serviceName: {{ $serviceName }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/webspa/templates/ingress.yaml b/deploy/k8s/helm/webspa/templates/ingress.yaml index 2b9fdd703..b684f4898 100644 --- a/deploy/k8s/helm/webspa/templates/ingress.yaml +++ b/deploy/k8s/helm/webspa/templates/ingress.yaml @@ -1,6 +1,8 @@ {{- if .Values.ingress.enabled -}} {{- $ingressPath := include "pathBase" . -}} -apiVersion: extensions/v1beta1 +{{- $serviceName := $.Values.app.svc.spa -}} + +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "webspa.fullname" . }} @@ -38,8 +40,11 @@ spec: http: paths: - path: {{ $ingressPath }} + pathType: Prefix backend: - serviceName: {{ $.Values.app.svc.spa }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/helm/webstatus/templates/ingress.yaml b/deploy/k8s/helm/webstatus/templates/ingress.yaml index 9902b86b5..6ec79d0dd 100644 --- a/deploy/k8s/helm/webstatus/templates/ingress.yaml +++ b/deploy/k8s/helm/webstatus/templates/ingress.yaml @@ -1,7 +1,9 @@ {{- if .Values.ingress.enabled -}} {{- $fullName := include "webstatus.fullname" . -}} {{- $ingressPath := include "pathBase" . -}} -apiVersion: extensions/v1beta1 +{{- $serviceName := $.Values.app.svc.status -}} + +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ template "webstatus.fullname" . }} @@ -39,8 +41,11 @@ spec: http: paths: - path: {{ $ingressPath }} + pathType: Prefix backend: - serviceName: {{ $.Values.app.svc.status }} - servicePort: http + service: + name: {{ $serviceName }} + port: + number: 80 {{- end }} {{- end }} diff --git a/deploy/k8s/nginx-ingress/local-cm.yaml b/deploy/k8s/nginx-ingress/local-cm.yaml index 02906afc1..4f4e4c930 100644 --- a/deploy/k8s/nginx-ingress/local-cm.yaml +++ b/deploy/k8s/nginx-ingress/local-cm.yaml @@ -4,7 +4,7 @@ metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx - name: nginx-configuration + name: ingress-nginx-controller namespace: ingress-nginx data: proxy-buffer-size: "128k" diff --git a/deploy/k8s/nginx-ingress/local-dockerk8s/mvc-fix.yaml b/deploy/k8s/nginx-ingress/local-dockerk8s/mvc-fix.yaml index b9ecd4cba..c5fbadbc0 100644 --- a/deploy/k8s/nginx-ingress/local-dockerk8s/mvc-fix.yaml +++ b/deploy/k8s/nginx-ingress/local-dockerk8s/mvc-fix.yaml @@ -1,4 +1,4 @@ -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: @@ -11,14 +11,18 @@ metadata: namespace: default spec: rules: - - http: - paths: - - backend: - serviceName: webmvc - servicePort: http - path: /webmvc + - host: localhost + http: + paths: + - path: /webmvc + pathType: Prefix + backend: + service: + name: webmvc + port: + number: 80 --- -apiVersion: extensions/v1beta1 +apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: @@ -31,9 +35,13 @@ metadata: namespace: default spec: rules: - - http: - paths: - - backend: - serviceName: identity - servicePort: http - path: /identity \ No newline at end of file + - host: localhost + http: + paths: + - path: /identity + pathType: Prefix + backend: + service: + name: identity + port: + number: 80 diff --git a/deploy/k8s/nginx-ingress/mandatory.yaml b/deploy/k8s/nginx-ingress/mandatory.yaml index 2e63edd59..8fd74f681 100644 --- a/deploy/k8s/nginx-ingress/mandatory.yaml +++ b/deploy/k8s/nginx-ingress/mandatory.yaml @@ -26,7 +26,7 @@ metadata: app.kubernetes.io/part-of: ingress-nginx --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nginx-ingress-clusterrole @@ -82,7 +82,7 @@ rules: - update --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: nginx-ingress-role @@ -127,7 +127,7 @@ rules: - get --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: nginx-ingress-role-nisa-binding @@ -145,7 +145,7 @@ subjects: namespace: ingress-nginx --- -apiVersion: rbac.authorization.k8s.io/v1beta1 +apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: nginx-ingress-clusterrole-nisa-binding diff --git a/deploy/windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 b/deploy/windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 index 9aad3e45c..8f4a5d783 100644 --- a/deploy/windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 +++ b/deploy/windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 @@ -10,10 +10,10 @@ function Check-Admin { $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) } function Add-InboundRule { - New-NetFirewallRule -DisplayName $InboundDisplayName -Confirm -Description "$Name Inbound Rule for port range 5100-5150" -LocalAddress Any -LocalPort 5100-5150 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound + New-NetFirewallRule -DisplayName $InboundDisplayName -Confirm -Description "$Name Inbound Rule for port range 5100-5205" -LocalAddress Any -LocalPort 5100-5205 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound } function Add-OutboundRule { - New-NetFirewallRule -DisplayName $OutboundDisplayName -Confirm -Description "$Name Outbound Rule for port range 5100-5150" -LocalAddress Any -LocalPort 5100-5150 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound + New-NetFirewallRule -DisplayName $OutboundDisplayName -Confirm -Description "$Name Outbound Rule for port range 5100-5205" -LocalAddress Any -LocalPort 5100-5205 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound } if ((Check-Admin) -eq $false) { diff --git a/img/eshop-spa-app-home.png b/img/eshop-spa-app-home.png new file mode 100644 index 000000000..a7093903d Binary files /dev/null and b/img/eshop-spa-app-home.png differ diff --git a/img/eshop-webmvc-app-screenshot.png b/img/eshop-webmvc-app-screenshot.png index 0c02fe8ed..9e354facd 100644 Binary files a/img/eshop-webmvc-app-screenshot.png and b/img/eshop-webmvc-app-screenshot.png differ diff --git a/src/ApiGateways/Envoy/config/mobileshopping/envoy.yaml b/src/ApiGateways/Envoy/config/mobileshopping/envoy.yaml index 1ae8c45a1..8f2162ad7 100644 --- a/src/ApiGateways/Envoy/config/mobileshopping/envoy.yaml +++ b/src/ApiGateways/Envoy/config/mobileshopping/envoy.yaml @@ -103,7 +103,7 @@ static_resources: lb_policy: round_robin hosts: - socket_address: - address: webshoppingagg + address: mobileshoppingagg port_value: 80 - name: catalog connect_timeout: 0.25s diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs index 90fa010cd..ccd733bc3 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Config/UrlsConfig.cs @@ -1,38 +1,35 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config +public class UrlsConfig { - public class UrlsConfig + public class CatalogOperations { - public class CatalogOperations - { - public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; + public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; - public static string GetItemsById(IEnumerable ids) => $"/api/v1/catalog/items?ids={string.Join(',', ids)}"; - } + public static string GetItemsById(IEnumerable ids) => $"/api/v1/catalog/items?ids={string.Join(',', ids)}"; + } - public class BasketOperations - { - public static string GetItemById(string id) => $"/api/v1/basket/{id}"; + public class BasketOperations + { + public static string GetItemById(string id) => $"/api/v1/basket/{id}"; - public static string UpdateBasket() => "/api/v1/basket"; - } + public static string UpdateBasket() => "/api/v1/basket"; + } - public class OrdersOperations - { - public static string GetOrderDraft() => "/api/v1/orders/draft"; - } + public class OrdersOperations + { + public static string GetOrderDraft() => "/api/v1/orders/draft"; + } - public string Basket { get; set; } + public string Basket { get; set; } - public string Catalog { get; set; } + public string Catalog { get; set; } - public string Orders { get; set; } + public string Orders { get; set; } - public string GrpcBasket { get; set; } + public string GrpcBasket { get; set; } - public string GrpcCatalog { get; set; } + public string GrpcCatalog { get; set; } - public string GrpcOrdering { get; set; } - } + public string GrpcOrdering { get; set; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs index 64399465a..a3cf4f03c 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -1,156 +1,145 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers; + +[Route("api/v1/[controller]")] +[Authorize] +[ApiController] +public class BasketController : ControllerBase { - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class BasketController : ControllerBase + private readonly ICatalogService _catalog; + private readonly IBasketService _basket; + + public BasketController(ICatalogService catalogService, IBasketService basketService) { - private readonly ICatalogService _catalog; - private readonly IBasketService _basket; + _catalog = catalogService; + _basket = basketService; + } - public BasketController(ICatalogService catalogService, IBasketService basketService) + [HttpPost] + [HttpPut] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] + public async Task> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data) + { + if (data.Items == null || !data.Items.Any()) { - _catalog = catalogService; - _basket = basketService; + return BadRequest("Need to pass at least one basket line"); } - [HttpPost] - [HttpPut] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] - public async Task> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data) + // Retrieve the current basket + var basket = await _basket.GetByIdAsync(data.BuyerId) ?? new BasketData(data.BuyerId); + var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); + // group by product id to avoid duplicates + var itemsCalculated = data + .Items + .GroupBy(x => x.ProductId, x => x, (k, i) => new { productId = k, items = i }) + .Select(groupedItem => + { + var item = groupedItem.items.First(); + item.Quantity = groupedItem.items.Sum(i => i.Quantity); + return item; + }); + + foreach (var bitem in itemsCalculated) { - if (data.Items == null || !data.Items.Any()) + var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); + if (catalogItem == null) { - return BadRequest("Need to pass at least one basket line"); + return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); } - // Retrieve the current basket - var basket = await _basket.GetById(data.BuyerId) ?? new BasketData(data.BuyerId); - - var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); - // group by product id to avoid duplicates - var itemsCalculated = data - .Items - .GroupBy(x => x.ProductId, x => x, (k, i) => new { productId = k, items = i }) - .Select(groupedItem => - { - var item = groupedItem.items.First(); - item.Quantity = groupedItem.items.Sum(i => i.Quantity); - return item; - }); - - foreach (var bitem in itemsCalculated) + var itemInBasket = basket.Items.FirstOrDefault(x => x.ProductId == bitem.ProductId); + if (itemInBasket == null) { - var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); - if (catalogItem == null) - { - return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); - } - - var itemInBasket = basket.Items.FirstOrDefault(x => x.ProductId == bitem.ProductId); - if (itemInBasket == null) - { - basket.Items.Add(new BasketDataItem() - { - Id = bitem.Id, - ProductId = catalogItem.Id, - ProductName = catalogItem.Name, - PictureUrl = catalogItem.PictureUri, - UnitPrice = catalogItem.Price, - Quantity = bitem.Quantity - }); - } - else + basket.Items.Add(new BasketDataItem() { - itemInBasket.Quantity = bitem.Quantity; - } + Id = bitem.Id, + ProductId = catalogItem.Id, + ProductName = catalogItem.Name, + PictureUrl = catalogItem.PictureUri, + UnitPrice = catalogItem.Price, + Quantity = bitem.Quantity + }); } + else + { + itemInBasket.Quantity = bitem.Quantity; + } + } - await _basket.UpdateAsync(basket); + await _basket.UpdateAsync(basket); + + return basket; + } - return basket; + [HttpPut] + [Route("items")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] + public async Task> UpdateQuantitiesAsync([FromBody] UpdateBasketItemsRequest data) + { + if (!data.Updates.Any()) + { + return BadRequest("No updates sent"); } - [HttpPut] - [Route("items")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] - public async Task> UpdateQuantitiesAsync([FromBody] UpdateBasketItemsRequest data) + // Retrieve the current basket + var currentBasket = await _basket.GetByIdAsync(data.BasketId); + if (currentBasket == null) { - if (!data.Updates.Any()) - { - return BadRequest("No updates sent"); - } + return BadRequest($"Basket with id {data.BasketId} not found."); + } - // Retrieve the current basket - var currentBasket = await _basket.GetById(data.BasketId); - if (currentBasket == null) - { - return BadRequest($"Basket with id {data.BasketId} not found."); - } + // Update with new quantities + foreach (var update in data.Updates) + { + var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); - // Update with new quantities - foreach (var update in data.Updates) + if (basketItem == null) { - var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); - - if (basketItem == null) - { - return BadRequest($"Basket item with id {update.BasketItemId} not found"); - } - - basketItem.Quantity = update.NewQty; + return BadRequest($"Basket item with id {update.BasketItemId} not found"); } - // Save the updated basket - await _basket.UpdateAsync(currentBasket); - - return currentBasket; + basketItem.Quantity = update.NewQty; } - [HttpPost] - [Route("items")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.OK)] - public async Task AddBasketItemAsync([FromBody] AddBasketItemRequest data) + // Save the updated basket + await _basket.UpdateAsync(currentBasket); + + return currentBasket; + } + + [HttpPost] + [Route("items")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.OK)] + public async Task AddBasketItemAsync([FromBody] AddBasketItemRequest data) + { + if (data == null || data.Quantity == 0) { - if (data == null || data.Quantity == 0) - { - return BadRequest("Invalid payload"); - } + return BadRequest("Invalid payload"); + } - // Step 1: Get the item from catalog - var item = await _catalog.GetCatalogItemAsync(data.CatalogItemId); + // Step 1: Get the item from catalog + var item = await _catalog.GetCatalogItemAsync(data.CatalogItemId); - //item.PictureUri = + //item.PictureUri = - // Step 2: Get current basket status - var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); - // Step 3: Merge current status with new product - currentBasket.Items.Add(new BasketDataItem() - { - UnitPrice = item.Price, - PictureUrl = item.PictureUri, - ProductId = item.Id, - ProductName = item.Name, - Quantity = data.Quantity, - Id = Guid.NewGuid().ToString() - }); - - // Step 4: Update basket - await _basket.UpdateAsync(currentBasket); - - return Ok(); - } + // Step 2: Get current basket status + var currentBasket = (await _basket.GetByIdAsync(data.BasketId)) ?? new BasketData(data.BasketId); + // Step 3: Merge current status with new product + currentBasket.Items.Add(new BasketDataItem() + { + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id, + ProductName = item.Name, + Quantity = data.Quantity, + Id = Guid.NewGuid().ToString() + }); + + // Step 4: Update basket + await _basket.UpdateAsync(currentBasket); + + return Ok(); } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs index e72e23ca7..5328f308d 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/HomeController.cs @@ -1,14 +1,11 @@ -using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers +[Route("")] +public class HomeController : Controller { - [Route("")] - public class HomeController : Controller + [HttpGet] + public IActionResult Index() { - [HttpGet()] - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } + return new RedirectResult("~/swagger"); } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs index 8bacc80d4..55b4dd70b 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Controllers/OrderController.cs @@ -1,45 +1,37 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -using System.Net; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers +[Route("api/v1/[controller]")] +[Authorize] +[ApiController] +public class OrderController : ControllerBase { - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class OrderController : ControllerBase + private readonly IBasketService _basketService; + private readonly IOrderingService _orderingService; + + public OrderController(IBasketService basketService, IOrderingService orderingService) { - private readonly IBasketService _basketService; - private readonly IOrderingService _orderingService; + _basketService = basketService; + _orderingService = orderingService; + } - public OrderController(IBasketService basketService, IOrderingService orderingService) + [Route("draft/{basketId}")] + [HttpGet] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(OrderData), (int)HttpStatusCode.OK)] + public async Task> GetOrderDraftAsync(string basketId) + { + if (string.IsNullOrEmpty(basketId)) { - _basketService = basketService; - _orderingService = orderingService; + return BadRequest("Need a valid basketid"); } + // Get the basket data and build a order draft based on it + var basket = await _basketService.GetByIdAsync(basketId); - [Route("draft/{basketId}")] - [HttpGet] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(OrderData), (int)HttpStatusCode.OK)] - public async Task> GetOrderDraftAsync(string basketId) + if (basket == null) { - if (string.IsNullOrEmpty(basketId)) - { - return BadRequest("Need a valid basketid"); - } - // Get the basket data and build a order draft based on it - var basket = await _basketService.GetById(basketId); - - if (basket == null) - { - return BadRequest($"No basket found for id {basketId}"); - } - - return await _orderingService.GetOrderDraftAsync(basket); + return BadRequest($"No basket found for id {basketId}"); } + + return await _orderingService.GetOrderDraftAsync(basket); } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile index ee0370910..aab4164b7 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop index b2a61dc7d..9a907ee69 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index e975edb23..11473d1c1 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -1,12 +1,5 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters { - namespace Basket.API.Infrastructure.Filters { public class AuthorizeCheckOperationFilter : IOperationFilter @@ -29,7 +22,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters operation.Security = new List { - new OpenApiSecurityRequirement + new() { [ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/GlobalUsings.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/GlobalUsings.cs new file mode 100644 index 000000000..881670f5e --- /dev/null +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/GlobalUsings.cs @@ -0,0 +1,41 @@ +global using CatalogApi; +global using Devspaces.Support; +global using Grpc.Core.Interceptors; +global using Grpc.Core; +global using GrpcBasket; +global using GrpcOrdering; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authentication; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore; +global using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; +global using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters; +global using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure; +global using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; +global using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; +global using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Microsoft.OpenApi.Models; +global using Serilog; +global using Swashbuckle.AspNetCore.SwaggerGen; +global using System.Collections.Generic; +global using System.IdentityModel.Tokens.Jwt; +global using System.Linq; +global using System.Net.Http.Headers; +global using System.Net.Http; +global using System.Net; +global using System.Text.Json; +global using System.Threading.Tasks; +global using System.Threading; +global using System; diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs index e74a4b2f5..c434074d3 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs @@ -1,41 +1,35 @@ -using Grpc.Core; -using Grpc.Core.Interceptors; -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure +public class GrpcExceptionInterceptor : Interceptor { - public class GrpcExceptionInterceptor : Interceptor + private readonly ILogger _logger; + + public GrpcExceptionInterceptor(ILogger logger) { - private readonly ILogger _logger; + _logger = logger; + } - public GrpcExceptionInterceptor(ILogger logger) - { - _logger = logger; - } + public override AsyncUnaryCall AsyncUnaryCall( + TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation) + { + var call = continuation(request, context); - public override AsyncUnaryCall AsyncUnaryCall( - TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) - { - var call = continuation(request, context); + return new AsyncUnaryCall(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); + } - return new AsyncUnaryCall(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); + private async Task HandleResponse(Task t) + { + try + { + var response = await t; + return response; } - - private async Task HandleResponse(Task t) + catch (RpcException e) { - try - { - var response = await t; - return response; - } - catch (RpcException e) - { - _logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message); - return default; - } + _logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message); + return default; } } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs index bfc705b5c..24914ca33 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs @@ -1,54 +1,44 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; -using System.Collections.Generic; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure -{ - public class HttpClientAuthorizationDelegatingHandler : DelegatingHandler - { - private readonly IHttpContextAccessor _httpContextAccesor; - private readonly ILogger _logger; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure; - public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor, ILogger logger) - { - _httpContextAccesor = httpContextAccesor; - _logger = logger; - } +public class HttpClientAuthorizationDelegatingHandler : DelegatingHandler +{ + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ILogger _logger; - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - request.Version = new System.Version(2, 0); - request.Method = HttpMethod.Get; + public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor, ILogger logger) + { + _httpContextAccessor = httpContextAccessor; + _logger = logger; + } - var authorizationHeader = _httpContextAccesor.HttpContext - .Request.Headers["Authorization"]; + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + request.Version = new System.Version(2, 0); + request.Method = HttpMethod.Get; - if (!string.IsNullOrEmpty(authorizationHeader)) - { - request.Headers.Add("Authorization", new List() { authorizationHeader }); - } + var authorizationHeader = _httpContextAccessor.HttpContext + .Request.Headers["Authorization"]; - var token = await GetToken(); + if (!string.IsNullOrEmpty(authorizationHeader)) + { + request.Headers.Add("Authorization", new List() { authorizationHeader }); + } - if (token != null) - { - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); - } + var token = await GetToken(); - return await base.SendAsync(request, cancellationToken); + if (token != null) + { + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } - async Task GetToken() - { - const string ACCESS_TOKEN = "access_token"; + return await base.SendAsync(request, cancellationToken); + } - return await _httpContextAccesor.HttpContext - .GetTokenAsync(ACCESS_TOKEN); - } + async Task GetToken() + { + const string ACCESS_TOKEN = "access_token"; + + return await _httpContextAccessor.HttpContext + .GetTokenAsync(ACCESS_TOKEN); } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj index 4a982fc2d..13c443025 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj @@ -1,13 +1,12 @@  - net5.0 + net6.0 Mobile.Shopping.HttpAggregator Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator ..\..\..\docker-compose.dcproj false - true - preview + true @@ -17,14 +16,13 @@ - + - + - diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs index d0271d84b..f7037d196 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs @@ -1,16 +1,15 @@ -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; + +public class AddBasketItemRequest { - public class AddBasketItemRequest - { - public int CatalogItemId { get; set; } + public int CatalogItemId { get; set; } - public string BasketId { get; set; } + public string BasketId { get; set; } - public int Quantity { get; set; } + public int Quantity { get; set; } - public AddBasketItemRequest() - { - Quantity = 1; - } + public AddBasketItemRequest() + { + Quantity = 1; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs index 7a43d58e5..d47e6efbd 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketData.cs @@ -1,22 +1,17 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +public class BasketData { + public string BuyerId { get; set; } - public class BasketData - { - public string BuyerId { get; set; } - - public List Items { get; set; } = new List(); - - public BasketData() - { - } + public List Items { get; set; } = new(); - public BasketData(string buyerId) - { - BuyerId = buyerId; - } + public BasketData() + { } + public BasketData(string buyerId) + { + BuyerId = buyerId; + } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketDataItem.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketDataItem.cs index 3ff91df4f..95bda8d37 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketDataItem.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/BasketDataItem.cs @@ -1,21 +1,18 @@ -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models -{ - - public class BasketDataItem - { - public string Id { get; set; } +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; - public int ProductId { get; set; } +public class BasketDataItem +{ + public string Id { get; set; } - public string ProductName { get; set; } + public int ProductId { get; set; } - public decimal UnitPrice { get; set; } + public string ProductName { get; set; } - public decimal OldUnitPrice { get; set; } + public decimal UnitPrice { get; set; } - public int Quantity { get; set; } + public decimal OldUnitPrice { get; set; } - public string PictureUrl { get; set; } - } + public int Quantity { get; set; } + public string PictureUrl { get; set; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs index 603c70bd7..7b673de3b 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/CatalogItem.cs @@ -1,13 +1,12 @@ -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; + +public class CatalogItem { - public class CatalogItem - { - public int Id { get; set; } + public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public decimal Price { get; set; } + public decimal Price { get; set; } - public string PictureUri { get; set; } - } + public string PictureUri { get; set; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs index 3ecddcf36..8761417ab 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderData.cs @@ -1,48 +1,42 @@ -using System; -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +public class OrderData { + public string OrderNumber { get; set; } - public class OrderData - { - public string OrderNumber { get; set; } + public DateTime Date { get; set; } - public DateTime Date { get; set; } + public string Status { get; set; } - public string Status { get; set; } + public decimal Total { get; set; } - public decimal Total { get; set; } + public string Description { get; set; } - public string Description { get; set; } + public string City { get; set; } - public string City { get; set; } + public string Street { get; set; } - public string Street { get; set; } + public string State { get; set; } - public string State { get; set; } + public string Country { get; set; } - public string Country { get; set; } + public string ZipCode { get; set; } - public string ZipCode { get; set; } + public string CardNumber { get; set; } - public string CardNumber { get; set; } + public string CardHolderName { get; set; } - public string CardHolderName { get; set; } + public bool IsDraft { get; set; } - public bool IsDraft { get; set; } + public DateTime CardExpiration { get; set; } - public DateTime CardExpiration { get; set; } + public string CardExpirationShort { get; set; } - public string CardExpirationShort { get; set; } + public string CardSecurityNumber { get; set; } - public string CardSecurityNumber { get; set; } + public int CardTypeId { get; set; } - public int CardTypeId { get; set; } - - public string Buyer { get; set; } - - public List OrderItems { get; } = new List(); - } + public string Buyer { get; set; } + public List OrderItems { get; } = new(); } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs index b3832fa21..f763a6923 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/OrderItemData.cs @@ -1,19 +1,16 @@ -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models -{ - - public class OrderItemData - { - public int ProductId { get; set; } +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; - public string ProductName { get; set; } +public class OrderItemData +{ + public int ProductId { get; set; } - public decimal UnitPrice { get; set; } + public string ProductName { get; set; } - public decimal Discount { get; set; } + public decimal UnitPrice { get; set; } - public int Units { get; set; } + public decimal Discount { get; set; } - public string PictureUrl { get; set; } - } + public int Units { get; set; } + public string PictureUrl { get; set; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs index f8ec70d5f..d1476c55a 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs @@ -1,16 +1,13 @@ -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models -{ +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; - public class UpdateBasketItemData - { - public string BasketItemId { get; set; } +public class UpdateBasketItemData +{ + public string BasketItemId { get; set; } - public int NewQty { get; set; } + public int NewQty { get; set; } - public UpdateBasketItemData() - { - NewQty = 0; - } + public UpdateBasketItemData() + { + NewQty = 0; } - } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs index 066f01a9c..d0686ef51 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs @@ -1,19 +1,14 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +public class UpdateBasketItemsRequest { - public class UpdateBasketItemsRequest - { - - public string BasketId { get; set; } + public string BasketId { get; set; } - public ICollection Updates { get; set; } + public ICollection Updates { get; set; } - public UpdateBasketItemsRequest() - { - Updates = new List(); - } + public UpdateBasketItemsRequest() + { + Updates = new List(); } - } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs index f8fb7eb03..200f3c375 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs @@ -1,13 +1,8 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models +public class UpdateBasketRequest { + public string BuyerId { get; set; } - public class UpdateBasketRequest - { - public string BuyerId { get; set; } - - public IEnumerable Items { get; set; } - } - -} + public IEnumerable Items { get; set; } +} \ No newline at end of file diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs index af28e0157..48ed593a1 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs @@ -1,13 +1,10 @@ -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models -{ - - public class UpdateBasketRequestItemData - { - public string Id { get; set; } // Basket id +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; - public int ProductId { get; set; } // Catalog item id +public class UpdateBasketRequestItemData +{ + public string Id { get; set; } // Basket id - public int Quantity { get; set; } // Quantity - } + public int ProductId { get; set; } // Catalog item id + public int Quantity { get; set; } // Quantity } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs index 3e80a543f..c5d6e10ff 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Program.cs @@ -1,10 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator; -using Serilog; - - -BuildWebHost(args).Run(); +await BuildWebHost(args).RunAsync(); IWebHost BuildWebHost(string[] args) => WebHost .CreateDefaultBuilder(args) diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs index d6217175b..b9fed393f 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/BasketService.cs @@ -1,90 +1,83 @@ -using GrpcBasket; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public class BasketService : IBasketService { - public class BasketService : IBasketService + private readonly Basket.BasketClient _basketClient; + private readonly ILogger _logger; + + public BasketService(Basket.BasketClient basketClient, ILogger logger) { - private readonly Basket.BasketClient _basketClient; - private readonly ILogger _logger; + _basketClient = basketClient; + _logger = logger; + } - public BasketService(Basket.BasketClient basketClient, ILogger logger) - { - _basketClient = basketClient; - _logger = logger; - } + public async Task GetByIdAsync(string id) + { + _logger.LogDebug("grpc client created, request = {@id}", id); + var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id }); + _logger.LogDebug("grpc response {@response}", response); - public async Task GetById(string id) - { - _logger.LogDebug("grpc client created, request = {@id}", id); - var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id }); - _logger.LogDebug("grpc response {@response}", response); + return MapToBasketData(response); + } - return MapToBasketData(response); - } + public async Task UpdateAsync(BasketData currentBasket) + { + _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); + var request = MapToCustomerBasketRequest(currentBasket); + _logger.LogDebug("Grpc update basket request {@request}", request); - public async Task UpdateAsync(BasketData currentBasket) - { - _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); - var request = MapToCustomerBasketRequest(currentBasket); - _logger.LogDebug("Grpc update basket request {@request}", request); + await _basketClient.UpdateBasketAsync(request); + } - await _basketClient.UpdateBasketAsync(request); + private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) + { + if (customerBasketRequest == null) + { + return null; } - private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) + var map = new BasketData { - if (customerBasketRequest == null) - { - return null; - } + BuyerId = customerBasketRequest.Buyerid + }; - var map = new BasketData - { - BuyerId = customerBasketRequest.Buyerid - }; + customerBasketRequest.Items.ToList().ForEach(item => map.Items.Add(new BasketDataItem + { + Id = item.Id, + OldUnitPrice = (decimal)item.Oldunitprice, + PictureUrl = item.Pictureurl, + ProductId = item.Productid, + ProductName = item.Productname, + Quantity = item.Quantity, + UnitPrice = (decimal)item.Unitprice + })); - customerBasketRequest.Items.ToList().ForEach(item => map.Items.Add(new BasketDataItem - { - Id = item.Id, - OldUnitPrice = (decimal)item.Oldunitprice, - PictureUrl = item.Pictureurl, - ProductId = item.Productid, - ProductName = item.Productname, - Quantity = item.Quantity, - UnitPrice = (decimal)item.Unitprice - })); + return map; + } - return map; + private CustomerBasketRequest MapToCustomerBasketRequest(BasketData basketData) + { + if (basketData == null) + { + return null; } - private CustomerBasketRequest MapToCustomerBasketRequest(BasketData basketData) + var map = new CustomerBasketRequest { - if (basketData == null) - { - return null; - } - - var map = new CustomerBasketRequest - { - Buyerid = basketData.BuyerId - }; + Buyerid = basketData.BuyerId + }; - basketData.Items.ToList().ForEach(item => map.Items.Add(new BasketItemResponse - { - Id = item.Id, - Oldunitprice = (double)item.OldUnitPrice, - Pictureurl = item.PictureUrl, - Productid = item.ProductId, - Productname = item.ProductName, - Quantity = item.Quantity, - Unitprice = (double)item.UnitPrice - })); + basketData.Items.ToList().ForEach(item => map.Items.Add(new BasketItemResponse + { + Id = item.Id, + Oldunitprice = (double)item.OldUnitPrice, + Pictureurl = item.PictureUrl, + Productid = item.ProductId, + Productname = item.ProductName, + Quantity = item.Quantity, + Unitprice = (double)item.UnitPrice + })); - return map; - } + return map; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs index 0101a7058..9fe1bdd5b 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/CatalogService.cs @@ -1,43 +1,36 @@ -using CatalogApi; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public class CatalogService : ICatalogService { - public class CatalogService : ICatalogService - { - private readonly Catalog.CatalogClient _client; + private readonly Catalog.CatalogClient _client; - public CatalogService(Catalog.CatalogClient client) - { - _client = client; - } + public CatalogService(Catalog.CatalogClient client) + { + _client = client; + } - public async Task GetCatalogItemAsync(int id) - { - var request = new CatalogItemRequest { Id = id }; - var response = await _client.GetItemByIdAsync(request); - return MapToCatalogItemResponse(response); - } + public async Task GetCatalogItemAsync(int id) + { + var request = new CatalogItemRequest { Id = id }; + var response = await _client.GetItemByIdAsync(request); + return MapToCatalogItemResponse(response); + } - public async Task> GetCatalogItemsAsync(IEnumerable ids) - { - var request = new CatalogItemsRequest { Ids = string.Join(",", ids), PageIndex = 1, PageSize = 10 }; - var response = await _client.GetItemsByIdsAsync(request); - return response.Data.Select(MapToCatalogItemResponse); - } + public async Task> GetCatalogItemsAsync(IEnumerable ids) + { + var request = new CatalogItemsRequest { Ids = string.Join(",", ids), PageIndex = 1, PageSize = 10 }; + var response = await _client.GetItemsByIdsAsync(request); + return response.Data.Select(MapToCatalogItemResponse); + } - private CatalogItem MapToCatalogItemResponse(CatalogItemResponse catalogItemResponse) + private CatalogItem MapToCatalogItemResponse(CatalogItemResponse catalogItemResponse) + { + return new CatalogItem { - return new CatalogItem - { - Id = catalogItemResponse.Id, - Name = catalogItemResponse.Name, - PictureUri = catalogItemResponse.PictureUri, - Price = (decimal)catalogItemResponse.Price - }; - } + Id = catalogItemResponse.Id, + Name = catalogItemResponse.Name, + PictureUri = catalogItemResponse.PictureUri, + Price = (decimal)catalogItemResponse.Price + }; } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs index d7a390c75..e1c9a24bf 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IBasketService.cs @@ -1,13 +1,9 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public interface IBasketService { - public interface IBasketService - { - Task GetById(string id); + Task GetByIdAsync(string id); - Task UpdateAsync(BasketData currentBasket); + Task UpdateAsync(BasketData currentBasket); - } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs index 832dfc740..83c95706e 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/ICatalogService.cs @@ -1,13 +1,8 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System.Collections.Generic; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public interface ICatalogService { - public interface ICatalogService - { - Task GetCatalogItemAsync(int id); + Task GetCatalogItemAsync(int id); - Task> GetCatalogItemsAsync(IEnumerable ids); - } + Task> GetCatalogItemsAsync(IEnumerable ids); } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs index 1abe545bd..5cda86223 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderApiClient.cs @@ -1,10 +1,6 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public interface IOrderApiClient { - public interface IOrderApiClient - { - Task GetOrderDraftFromBasketAsync(BasketData basket); - } + Task GetOrderDraftFromBasketAsync(BasketData basket); } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs index 5518a4bbf..fd492f698 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/IOrderingService.cs @@ -1,10 +1,6 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public interface IOrderingService { - public interface IOrderingService - { - Task GetOrderDraftAsync(BasketData basketData); - } -} \ No newline at end of file + Task GetOrderDraftAsync(BasketData basketData); +} diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs index da39abbff..6a8465df6 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderApiClient.cs @@ -1,37 +1,31 @@ -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System.Net.Http; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public class OrderApiClient : IOrderApiClient { - public class OrderApiClient : IOrderApiClient - { - private readonly HttpClient _apiClient; - private readonly ILogger _logger; - private readonly UrlsConfig _urls; + private readonly HttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; - public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config) - { - _apiClient = httpClient; - _logger = logger; - _urls = config.Value; - } + public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } - public async Task GetOrderDraftFromBasketAsync(BasketData basket) - { - var uri = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft(); - var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json"); - var response = await _apiClient.PostAsync(uri, content); + public async Task GetOrderDraftFromBasketAsync(BasketData basket) + { + var uri = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft(); + var content = new StringContent(JsonSerializer.Serialize(basket), System.Text.Encoding.UTF8, "application/json"); + var response = await _apiClient.PostAsync(uri, content); - response.EnsureSuccessStatusCode(); + response.EnsureSuccessStatusCode(); - var ordersDraftResponse = await response.Content.ReadAsStringAsync(); + var ordersDraftResponse = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(ordersDraftResponse); - } + return JsonSerializer.Deserialize(ordersDraftResponse, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); } } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs index 7f9d5deb7..2a7de50a7 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Services/OrderingService.cs @@ -1,79 +1,72 @@ -using GrpcOrdering; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services +public class OrderingService : IOrderingService { - public class OrderingService : IOrderingService + private readonly OrderingGrpc.OrderingGrpcClient _orderingGrpcClient; + private readonly ILogger _logger; + + public OrderingService(OrderingGrpc.OrderingGrpcClient orderingGrpcClient, ILogger logger) { - private readonly OrderingGrpc.OrderingGrpcClient _orderingGrpcClient; - private readonly ILogger _logger; + _orderingGrpcClient = orderingGrpcClient; + _logger = logger; + } - public OrderingService(OrderingGrpc.OrderingGrpcClient orderingGrpcClient, ILogger logger) - { - _orderingGrpcClient = orderingGrpcClient; - _logger = logger; - } + public async Task GetOrderDraftAsync(BasketData basketData) + { + _logger.LogDebug(" grpc client created, basketData={@basketData}", basketData); - public async Task GetOrderDraftAsync(BasketData basketData) - { - _logger.LogDebug(" grpc client created, basketData={@basketData}", basketData); + var command = MapToOrderDraftCommand(basketData); + var response = await _orderingGrpcClient.CreateOrderDraftFromBasketDataAsync(command); + _logger.LogDebug(" grpc response: {@response}", response); - var command = MapToOrderDraftCommand(basketData); - var response = await _orderingGrpcClient.CreateOrderDraftFromBasketDataAsync(command); - _logger.LogDebug(" grpc response: {@response}", response); + return MapToResponse(response, basketData); + } - return MapToResponse(response, basketData); + private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft, BasketData basketData) + { + if (orderDraft == null) + { + return null; } - private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft, BasketData basketData) + var data = new OrderData { - if (orderDraft == null) - { - return null; - } + Buyer = basketData.BuyerId, + Total = (decimal)orderDraft.Total, + }; - var data = new OrderData - { - Buyer = basketData.BuyerId, - Total = (decimal)orderDraft.Total, - }; - - orderDraft.OrderItems.ToList().ForEach(o => data.OrderItems.Add(new OrderItemData - { - Discount = (decimal)o.Discount, - PictureUrl = o.PictureUrl, - ProductId = o.ProductId, - ProductName = o.ProductName, - UnitPrice = (decimal)o.UnitPrice, - Units = o.Units, - })); + orderDraft.OrderItems.ToList().ForEach(o => data.OrderItems.Add(new OrderItemData + { + Discount = (decimal)o.Discount, + PictureUrl = o.PictureUrl, + ProductId = o.ProductId, + ProductName = o.ProductName, + UnitPrice = (decimal)o.UnitPrice, + Units = o.Units, + })); - return data; - } + return data; + } - private CreateOrderDraftCommand MapToOrderDraftCommand(BasketData basketData) + private CreateOrderDraftCommand MapToOrderDraftCommand(BasketData basketData) + { + var command = new CreateOrderDraftCommand { - var command = new CreateOrderDraftCommand - { - BuyerId = basketData.BuyerId, - }; + BuyerId = basketData.BuyerId, + }; - basketData.Items.ForEach(i => command.Items.Add(new BasketItem - { - Id = i.Id, - OldUnitPrice = (double)i.OldUnitPrice, - PictureUrl = i.PictureUrl, - ProductId = i.ProductId, - ProductName = i.ProductName, - Quantity = i.Quantity, - UnitPrice = (double)i.UnitPrice, - })); - - return command; - } + basketData.Items.ForEach(i => command.Items.Add(new BasketItem + { + Id = i.Id, + OldUnitPrice = (double)i.OldUnitPrice, + PictureUrl = i.PictureUrl, + ProductId = i.ProductId, + ProductName = i.ProductName, + Quantity = i.Quantity, + UnitPrice = (double)i.UnitPrice, + })); + return command; } + } diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs index 3e1ec3887..3f988395a 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs @@ -1,222 +1,196 @@ -using CatalogApi; -using Devspaces.Support; -using GrpcBasket; -using GrpcOrdering; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure; -using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; - -namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator +namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddHealthChecks() + .AddCheck("self", () => HealthCheckResult.Healthy()) + .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) + .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) + .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) + .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) + .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }); + + services.AddCustomMvc(Configuration) + .AddCustomAuthentication(Configuration) + .AddDevspaces() + .AddHttpServices() + .AddGrpcServices(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + var pathBase = Configuration["PATH_BASE"]; + + if (!string.IsNullOrEmpty(pathBase)) { - services.AddHealthChecks() - .AddCheck("self", () => HealthCheckResult.Healthy()) - .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) - .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) - .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) - .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) - .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }); - - services.AddCustomMvc(Configuration) - .AddCustomAuthentication(Configuration) - .AddDevspaces() - .AddHttpServices() - .AddGrpcServices(); + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + if (env.IsDevelopment()) { - var pathBase = Configuration["PATH_BASE"]; - - if (!string.IsNullOrEmpty(pathBase)) - { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); - app.UsePathBase(pathBase); - } - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } + app.UseDeveloperExceptionPage(); + } - app.UseSwagger().UseSwaggerUI(c => + app.UseSwagger().UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); + + c.OAuthClientId("mobileshoppingaggswaggerui"); + c.OAuthClientSecret(string.Empty); + c.OAuthRealm(string.Empty); + c.OAuthAppName("Purchase BFF Swagger UI"); + }); + + app.UseRouting(); + app.UseCors("CorsPolicy"); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); - - c.OAuthClientId("mobileshoppingaggswaggerui"); - c.OAuthClientSecret(string.Empty); - c.OAuthRealm(string.Empty); - c.OAuthAppName("Purchase BFF Swagger UI"); + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); - - app.UseRouting(); - app.UseCors("CorsPolicy"); - app.UseAuthentication(); - app.UseAuthorization(); - app.UseEndpoints(endpoints => + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); + Predicate = r => r.Name.Contains("self") }); - } + }); } +} - public static class ServiceCollectionExtensions +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions(); - services.Configure(configuration.GetSection("urls")); + services.AddOptions(); + services.Configure(configuration.GetSection("urls")); - services.AddControllers() - .AddNewtonsoftJson(); + services.AddControllers() + .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); - services.AddSwaggerGen(options => + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new OpenApiInfo { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "Shopping Aggregator for Mobile Clients", - Version = "v1", - Description = "Shopping Aggregator for Mobile Clients" - }); - options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + Title = "Shopping Aggregator for Mobile Clients", + Version = "v1", + Description = "Shopping Aggregator for Mobile Clients" + }); + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() + Implicit = new OpenApiOAuthFlow() { - Implicit = new OpenApiOAuthFlow() - { - AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), - TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), + AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), + TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), - Scopes = new Dictionary() - { - { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } - } + Scopes = new Dictionary() + { + { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } } } - }); - - options.OperationFilter(); + } }); - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .AllowAnyMethod() - .AllowAnyHeader() - .SetIsOriginAllowed((host) => true) - .AllowCredentials()); - }); + options.OperationFilter(); + }); - return services; - } - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + services.AddCors(options => { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - - var identityUrl = configuration.GetValue("urls:identity"); - - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + options.AddPolicy("CorsPolicy", + builder => builder + .AllowAnyMethod() + .AllowAnyHeader() + .SetIsOriginAllowed((host) => true) + .AllowCredentials()); + }); + + return services; + } + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - }) - .AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "mobileshoppingagg"; - }); + var identityUrl = configuration.GetValue("urls:identity"); - return services; - } + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - public static IServiceCollection AddHttpServices(this IServiceCollection services) + }) + .AddJwtBearer(options => { - //register delegating handlers - services.AddTransient(); - services.AddSingleton(); + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "mobileshoppingagg"; + }); - //register http services + return services; + } - services.AddHttpClient() - .AddDevspacesSupport(); + public static IServiceCollection AddHttpServices(this IServiceCollection services) + { + //register delegating handlers + services.AddTransient(); + services.AddSingleton(); - return services; - } + //register http services - public static IServiceCollection AddGrpcServices(this IServiceCollection services) - { - services.AddTransient(); + services.AddHttpClient() + .AddDevspacesSupport(); - services.AddScoped(); + return services; + } - services.AddGrpcClient((services, options) => - { - var basketApi = services.GetRequiredService>().Value.GrpcBasket; - options.Address = new Uri(basketApi); - }).AddInterceptor(); + public static IServiceCollection AddGrpcServices(this IServiceCollection services) + { + services.AddTransient(); - services.AddScoped(); + services.AddScoped(); - services.AddGrpcClient((services, options) => - { - var catalogApi = services.GetRequiredService>().Value.GrpcCatalog; - options.Address = new Uri(catalogApi); - }).AddInterceptor(); + services.AddGrpcClient((services, options) => + { + var basketApi = services.GetRequiredService>().Value.GrpcBasket; + options.Address = new Uri(basketApi); + }).AddInterceptor(); - services.AddScoped(); + services.AddScoped(); - services.AddGrpcClient((services, options) => - { - var orderingApi = services.GetRequiredService>().Value.GrpcOrdering; - options.Address = new Uri(orderingApi); - }).AddInterceptor(); + services.AddGrpcClient((services, options) => + { + var catalogApi = services.GetRequiredService>().Value.GrpcCatalog; + options.Address = new Uri(catalogApi); + }).AddInterceptor(); - return services; - } + services.AddScoped(); + services.AddGrpcClient((services, options) => + { + var orderingApi = services.GetRequiredService>().Value.GrpcOrdering; + options.Address = new Uri(orderingApi); + }).AddInterceptor(); + + return services; } + } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs index b19874aac..9b3391692 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Config/UrlsConfig.cs @@ -1,45 +1,41 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config +public class UrlsConfig { - public class UrlsConfig + public class CatalogOperations { + // grpc call under REST must go trough port 80 + public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; - public class CatalogOperations - { - // grpc call under REST must go trough port 80 - public static string GetItemById(int id) => $"/api/v1/catalog/items/{id}"; + public static string GetItemById(string ids) => $"/api/v1/catalog/items/ids/{string.Join(',', ids)}"; - public static string GetItemById(string ids) => $"/api/v1/catalog/items/ids/{string.Join(',', ids)}"; - - // REST call standard must go through port 5000 - public static string GetItemsById(IEnumerable ids) => $":5000/api/v1/catalog/items?ids={string.Join(',', ids)}"; - } - - public class BasketOperations - { - public static string GetItemById(string id) => $"/api/v1/basket/{id}"; + // REST call standard must go through port 5000 + public static string GetItemsById(IEnumerable ids) => $":5000/api/v1/catalog/items?ids={string.Join(',', ids)}"; + } - public static string UpdateBasket() => "/api/v1/basket"; - } + public class BasketOperations + { + public static string GetItemById(string id) => $"/api/v1/basket/{id}"; - public class OrdersOperations - { - public static string GetOrderDraft() => "/api/v1/orders/draft"; - } + public static string UpdateBasket() => "/api/v1/basket"; + } - public string Basket { get; set; } + public class OrdersOperations + { + public static string GetOrderDraft() => "/api/v1/orders/draft"; + } - public string Catalog { get; set; } + public string Basket { get; set; } - public string Orders { get; set; } + public string Catalog { get; set; } - public string GrpcBasket { get; set; } + public string Orders { get; set; } - public string GrpcCatalog { get; set; } + public string GrpcBasket { get; set; } - public string GrpcOrdering { get; set; } - } + public string GrpcCatalog { get; set; } + public string GrpcOrdering { get; set; } } + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs index 9471c6e09..143ff9a2b 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/BasketController.cs @@ -1,164 +1,154 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -using System; -using System.Linq; -using System.Net; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers; + +[Route("api/v1/[controller]")] +[Authorize] +[ApiController] +public class BasketController : ControllerBase { - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class BasketController : ControllerBase + private readonly ICatalogService _catalog; + private readonly IBasketService _basket; + + public BasketController(ICatalogService catalogService, IBasketService basketService) { - private readonly ICatalogService _catalog; - private readonly IBasketService _basket; + _catalog = catalogService; + _basket = basketService; + } - public BasketController(ICatalogService catalogService, IBasketService basketService) + [HttpPost] + [HttpPut] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] + public async Task> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data) + { + if (data.Items == null || !data.Items.Any()) { - _catalog = catalogService; - _basket = basketService; + return BadRequest("Need to pass at least one basket line"); } - [HttpPost] - [HttpPut] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] - public async Task> UpdateAllBasketAsync([FromBody] UpdateBasketRequest data) + // Retrieve the current basket + var basket = await _basket.GetByIdAsync(data.BuyerId) ?? new BasketData(data.BuyerId); + var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); + + // group by product id to avoid duplicates + var itemsCalculated = data + .Items + .GroupBy(x => x.ProductId, x => x, (k, i) => new { productId = k, items = i }) + .Select(groupedItem => + { + var item = groupedItem.items.First(); + item.Quantity = groupedItem.items.Sum(i => i.Quantity); + return item; + }); + + foreach (var bitem in itemsCalculated) { - if (data.Items == null || !data.Items.Any()) + var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); + if (catalogItem == null) { - return BadRequest("Need to pass at least one basket line"); + return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); } - // Retrieve the current basket - var basket = await _basket.GetById(data.BuyerId) ?? new BasketData(data.BuyerId); - var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId)); - - // group by product id to avoid duplicates - var itemsCalculated = data - .Items - .GroupBy(x => x.ProductId, x => x, (k, i) => new { productId = k, items = i }) - .Select(groupedItem => - { - var item = groupedItem.items.First(); - item.Quantity = groupedItem.items.Sum(i => i.Quantity); - return item; - }); - - foreach (var bitem in itemsCalculated) + var itemInBasket = basket.Items.FirstOrDefault(x => x.ProductId == bitem.ProductId); + if (itemInBasket == null) { - var catalogItem = catalogItems.SingleOrDefault(ci => ci.Id == bitem.ProductId); - if (catalogItem == null) - { - return BadRequest($"Basket refers to a non-existing catalog item ({bitem.ProductId})"); - } - - var itemInBasket = basket.Items.FirstOrDefault(x => x.ProductId == bitem.ProductId); - if (itemInBasket == null) - { - basket.Items.Add(new BasketDataItem() - { - Id = bitem.Id, - ProductId = catalogItem.Id, - ProductName = catalogItem.Name, - PictureUrl = catalogItem.PictureUri, - UnitPrice = catalogItem.Price, - Quantity = bitem.Quantity - }); - } - else + basket.Items.Add(new BasketDataItem() { - itemInBasket.Quantity = bitem.Quantity; - } + Id = bitem.Id, + ProductId = catalogItem.Id, + ProductName = catalogItem.Name, + PictureUrl = catalogItem.PictureUri, + UnitPrice = catalogItem.Price, + Quantity = bitem.Quantity + }); } + else + { + itemInBasket.Quantity = bitem.Quantity; + } + } - await _basket.UpdateAsync(basket); + await _basket.UpdateAsync(basket); - return basket; - } + return basket; + } - [HttpPut] - [Route("items")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] - public async Task> UpdateQuantitiesAsync([FromBody] UpdateBasketItemsRequest data) + [HttpPut] + [Route("items")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(BasketData), (int)HttpStatusCode.OK)] + public async Task> UpdateQuantitiesAsync([FromBody] UpdateBasketItemsRequest data) + { + if (!data.Updates.Any()) { - if (!data.Updates.Any()) - { - return BadRequest("No updates sent"); - } + return BadRequest("No updates sent"); + } - // Retrieve the current basket - var currentBasket = await _basket.GetById(data.BasketId); - if (currentBasket == null) - { - return BadRequest($"Basket with id {data.BasketId} not found."); - } + // Retrieve the current basket + var currentBasket = await _basket.GetByIdAsync(data.BasketId); + if (currentBasket == null) + { + return BadRequest($"Basket with id {data.BasketId} not found."); + } - // Update with new quantities - foreach (var update in data.Updates) + // Update with new quantities + foreach (var update in data.Updates) + { + var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); + if (basketItem == null) { - var basketItem = currentBasket.Items.SingleOrDefault(bitem => bitem.Id == update.BasketItemId); - if (basketItem == null) - { - return BadRequest($"Basket item with id {update.BasketItemId} not found"); - } - basketItem.Quantity = update.NewQty; + return BadRequest($"Basket item with id {update.BasketItemId} not found"); } + basketItem.Quantity = update.NewQty; + } - // Save the updated basket - await _basket.UpdateAsync(currentBasket); + // Save the updated basket + await _basket.UpdateAsync(currentBasket); - return currentBasket; - } + return currentBasket; + } - [HttpPost] - [Route("items")] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType((int)HttpStatusCode.OK)] - public async Task AddBasketItemAsync([FromBody] AddBasketItemRequest data) + [HttpPost] + [Route("items")] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType((int)HttpStatusCode.OK)] + public async Task AddBasketItemAsync([FromBody] AddBasketItemRequest data) + { + if (data == null || data.Quantity == 0) { - if (data == null || data.Quantity == 0) - { - return BadRequest("Invalid payload"); - } + return BadRequest("Invalid payload"); + } - // Step 1: Get the item from catalog - var item = await _catalog.GetCatalogItemAsync(data.CatalogItemId); + // Step 1: Get the item from catalog + var item = await _catalog.GetCatalogItemAsync(data.CatalogItemId); - //item.PictureUri = + //item.PictureUri = - // Step 2: Get current basket status - var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId); - // Step 3: Search if exist product into basket - var product = currentBasket.Items.SingleOrDefault(i => i.ProductId == item.Id); - if (product != null) - { - // Step 4: Update quantity for product - product.Quantity += data.Quantity; - } - else + // Step 2: Get current basket status + var currentBasket = (await _basket.GetByIdAsync(data.BasketId)) ?? new BasketData(data.BasketId); + // Step 3: Search if exist product into basket + var product = currentBasket.Items.SingleOrDefault(i => i.ProductId == item.Id); + if (product != null) + { + // Step 4: Update quantity for product + product.Quantity += data.Quantity; + } + else + { + // Step 4: Merge current status with new product + currentBasket.Items.Add(new BasketDataItem() { - // Step 4: Merge current status with new product - currentBasket.Items.Add(new BasketDataItem() - { - UnitPrice = item.Price, - PictureUrl = item.PictureUri, - ProductId = item.Id, - ProductName = item.Name, - Quantity = data.Quantity, - Id = Guid.NewGuid().ToString() - }); - } + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id, + ProductName = item.Name, + Quantity = data.Quantity, + Id = Guid.NewGuid().ToString() + }); + } - // Step 5: Update basket - await _basket.UpdateAsync(currentBasket); + // Step 5: Update basket + await _basket.UpdateAsync(currentBasket); - return Ok(); - } + return Ok(); } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs index e742e2bd6..55df5880b 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/HomeController.cs @@ -1,14 +1,11 @@ -using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers +[Route("")] +public class HomeController : Controller { - [Route("")] - public class HomeController : Controller + [HttpGet] + public IActionResult Index() { - [HttpGet()] - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } + return new RedirectResult("~/swagger"); } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs index e528b478f..448bbec85 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Controllers/OrderController.cs @@ -1,44 +1,37 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -using System.Net; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Controllers +[Route("api/v1/[controller]")] +[Authorize] +[ApiController] +public class OrderController : ControllerBase { - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class OrderController : ControllerBase + private readonly IBasketService _basketService; + private readonly IOrderingService _orderingService; + + public OrderController(IBasketService basketService, IOrderingService orderingService) + { + _basketService = basketService; + _orderingService = orderingService; + } + + [Route("draft/{basketId}")] + [HttpGet] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(OrderData), (int)HttpStatusCode.OK)] + public async Task> GetOrderDraftAsync(string basketId) { - private readonly IBasketService _basketService; - private readonly IOrderingService _orderingService; - public OrderController(IBasketService basketService, IOrderingService orderingService) + if (string.IsNullOrWhiteSpace(basketId)) { - _basketService = basketService; - _orderingService = orderingService; + return BadRequest("Need a valid basketid"); } + // Get the basket data and build a order draft based on it + var basket = await _basketService.GetByIdAsync(basketId); - [Route("draft/{basketId}")] - [HttpGet] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(OrderData), (int)HttpStatusCode.OK)] - public async Task> GetOrderDraftAsync(string basketId) + if (basket == null) { - if (string.IsNullOrEmpty(basketId)) - { - return BadRequest("Need a valid basketid"); - } - // Get the basket data and build a order draft based on it - var basket = await _basketService.GetById(basketId); - - if (basket == null) - { - return BadRequest($"No basket found for id {basketId}"); - } - - return await _orderingService.GetOrderDraftAsync(basket); + return BadRequest($"No basket found for id {basketId}"); } + + return await _orderingService.GetOrderDraftAsync(basket); } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile index 5736c19f7..8761763a1 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop index 462afbcd9..268a9c3ba 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs index c273fd19e..99bf07048 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Filters/AuthorizeCheckOperationFilter.cs @@ -1,10 +1,4 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters { namespace Basket.API.Infrastructure.Filters { @@ -14,7 +8,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters { // Check for authorize attribute var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || - context.MethodInfo.GetCustomAttributes(true).OfType().Any(); + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); if (!hasAuthorize) return; @@ -27,13 +21,14 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters }; operation.Security = new List + { + new() { - new OpenApiSecurityRequirement - { - [ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } - } - }; + [ oAuthScheme ] = new[] { "Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator" } + } + }; } } } -} + +} \ No newline at end of file diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/GlobalUsings.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/GlobalUsings.cs new file mode 100644 index 000000000..6162c557e --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/GlobalUsings.cs @@ -0,0 +1,41 @@ +global using CatalogApi; +global using Devspaces.Support; +global using Grpc.Core.Interceptors; +global using Grpc.Core; +global using GrpcBasket; +global using GrpcOrdering; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authentication; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore; +global using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; +global using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters; +global using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure; +global using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; +global using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; +global using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Microsoft.OpenApi.Models; +global using Serilog; +global using Swashbuckle.AspNetCore.SwaggerGen; +global using System.Collections.Generic; +global using System.IdentityModel.Tokens.Jwt; +global using System.Linq; +global using System.Net.Http.Headers; +global using System.Net.Http; +global using System.Net; +global using System.Text.Json; +global using System.Threading.Tasks; +global using System.Threading; +global using System; diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs index dc6b7e6f8..20adb2fc7 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/GrpcExceptionInterceptor.cs @@ -1,41 +1,35 @@ -using Grpc.Core; -using Grpc.Core.Interceptors; -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure +public class GrpcExceptionInterceptor : Interceptor { - public class GrpcExceptionInterceptor : Interceptor + private readonly ILogger _logger; + + public GrpcExceptionInterceptor(ILogger logger) { - private readonly ILogger _logger; + _logger = logger; + } - public GrpcExceptionInterceptor(ILogger logger) - { - _logger = logger; - } + public override AsyncUnaryCall AsyncUnaryCall( + TRequest request, + ClientInterceptorContext context, + AsyncUnaryCallContinuation continuation) + { + var call = continuation(request, context); - public override AsyncUnaryCall AsyncUnaryCall( - TRequest request, - ClientInterceptorContext context, - AsyncUnaryCallContinuation continuation) - { - var call = continuation(request, context); + return new AsyncUnaryCall(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); + } - return new AsyncUnaryCall(HandleResponse(call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose); + private async Task HandleResponse(Task task) + { + try + { + var response = await task; + return response; } - - private async Task HandleResponse(Task t) + catch (RpcException e) { - try - { - var response = await t; - return response; - } - catch (RpcException e) - { - _logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message); - return default; - } + _logger.LogError("Error calling via grpc: {Status} - {Message}", e.Status, e.Message); + return default; } } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs index 4e54829f8..d9b3b0ee1 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs @@ -1,49 +1,40 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; -using System.Collections.Generic; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure; + +public class HttpClientAuthorizationDelegatingHandler + : DelegatingHandler { - public class HttpClientAuthorizationDelegatingHandler - : DelegatingHandler + private readonly IHttpContextAccessor _httpContextAccessor; + + public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor) { - private readonly IHttpContextAccessor _httpContextAccesor; + _httpContextAccessor = httpContextAccessor; + } - public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor) - { - _httpContextAccesor = httpContextAccesor; - } + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var authorizationHeader = _httpContextAccessor.HttpContext + .Request.Headers["Authorization"]; - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + if (!string.IsNullOrWhiteSpace(authorizationHeader)) { - var authorizationHeader = _httpContextAccesor.HttpContext - .Request.Headers["Authorization"]; - - if (!string.IsNullOrEmpty(authorizationHeader)) - { - request.Headers.Add("Authorization", new List() { authorizationHeader }); - } - - var token = await GetToken(); + request.Headers.Add("Authorization", new List() { authorizationHeader }); + } - if (token != null) - { - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); - } + var token = await GetTokenAsync(); - return await base.SendAsync(request, cancellationToken); + if (token != null) + { + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } - async Task GetToken() - { - const string ACCESS_TOKEN = "access_token"; + return await base.SendAsync(request, cancellationToken); + } - return await _httpContextAccesor.HttpContext - .GetTokenAsync(ACCESS_TOKEN); - } + Task GetTokenAsync() + { + const string ACCESS_TOKEN = "access_token"; + + return _httpContextAccessor.HttpContext + .GetTokenAsync(ACCESS_TOKEN); } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs index e9a6492c0..f5905a499 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/AddBasketItemRequest.cs @@ -1,18 +1,16 @@ -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models -{ +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; - public class AddBasketItemRequest - { - public int CatalogItemId { get; set; } +public class AddBasketItemRequest +{ + public int CatalogItemId { get; set; } - public string BasketId { get; set; } + public string BasketId { get; set; } - public int Quantity { get; set; } + public int Quantity { get; set; } - public AddBasketItemRequest() - { - Quantity = 1; - } + public AddBasketItemRequest() + { + Quantity = 1; } - } + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs index 18e855837..942eb6b74 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketData.cs @@ -1,22 +1,18 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +public class BasketData { + public string BuyerId { get; set; } - public class BasketData - { - public string BuyerId { get; set; } - - public List Items { get; set; } = new List(); + public List Items { get; set; } = new(); - public BasketData() - { - } - - public BasketData(string buyerId) - { - BuyerId = buyerId; - } + public BasketData() + { } + public BasketData(string buyerId) + { + BuyerId = buyerId; + } } + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketDataItem.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketDataItem.cs index 05fed054e..6c11ab51f 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketDataItem.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/BasketDataItem.cs @@ -1,21 +1,18 @@ -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models -{ - - public class BasketDataItem - { - public string Id { get; set; } +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; - public int ProductId { get; set; } +public class BasketDataItem +{ + public string Id { get; set; } - public string ProductName { get; set; } + public int ProductId { get; set; } - public decimal UnitPrice { get; set; } + public string ProductName { get; set; } - public decimal OldUnitPrice { get; set; } + public decimal UnitPrice { get; set; } - public int Quantity { get; set; } + public decimal OldUnitPrice { get; set; } - public string PictureUrl { get; set; } - } + public int Quantity { get; set; } + public string PictureUrl { get; set; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs index 68c856970..0d598d95f 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/CatalogItem.cs @@ -1,15 +1,14 @@ -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; + +public class CatalogItem { + public int Id { get; set; } - public class CatalogItem - { - public int Id { get; set; } + public string Name { get; set; } - public string Name { get; set; } + public decimal Price { get; set; } - public decimal Price { get; set; } + public string PictureUri { get; set; } +} - public string PictureUri { get; set; } - } -} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs index c4536d697..519139e77 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderData.cs @@ -1,48 +1,43 @@ -using System; -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +public class OrderData { + public string OrderNumber { get; set; } - public class OrderData - { - public string OrderNumber { get; set; } + public DateTime Date { get; set; } - public DateTime Date { get; set; } + public string Status { get; set; } - public string Status { get; set; } + public decimal Total { get; set; } - public decimal Total { get; set; } + public string Description { get; set; } - public string Description { get; set; } + public string City { get; set; } - public string City { get; set; } + public string Street { get; set; } - public string Street { get; set; } + public string State { get; set; } - public string State { get; set; } + public string Country { get; set; } - public string Country { get; set; } + public string ZipCode { get; set; } - public string ZipCode { get; set; } + public string CardNumber { get; set; } - public string CardNumber { get; set; } + public string CardHolderName { get; set; } - public string CardHolderName { get; set; } + public bool IsDraft { get; set; } - public bool IsDraft { get; set; } + public DateTime CardExpiration { get; set; } - public DateTime CardExpiration { get; set; } + public string CardExpirationShort { get; set; } - public string CardExpirationShort { get; set; } + public string CardSecurityNumber { get; set; } - public string CardSecurityNumber { get; set; } + public int CardTypeId { get; set; } - public int CardTypeId { get; set; } - - public string Buyer { get; set; } - - public List OrderItems { get; } = new List(); - } + public string Buyer { get; set; } + public List OrderItems { get; } = new(); } + diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs index 0c2082fa2..cc533966f 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/OrderItemData.cs @@ -1,19 +1,16 @@ -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models -{ - - public class OrderItemData - { - public int ProductId { get; set; } +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; - public string ProductName { get; set; } +public class OrderItemData +{ + public int ProductId { get; set; } - public decimal UnitPrice { get; set; } + public string ProductName { get; set; } - public decimal Discount { get; set; } + public decimal UnitPrice { get; set; } - public int Units { get; set; } + public decimal Discount { get; set; } - public string PictureUrl { get; set; } - } + public int Units { get; set; } + public string PictureUrl { get; set; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs index b75784aa2..f7fa06798 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemData.cs @@ -1,16 +1,9 @@ -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models -{ - - public class UpdateBasketItemData - { - public string BasketItemId { get; set; } +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; - public int NewQty { get; set; } +public class UpdateBasketItemData +{ + public string BasketItemId { get; set; } - public UpdateBasketItemData() - { - NewQty = 0; - } - } + public int NewQty { get; set; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs index 3e356dfe1..26bbb58e4 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketItemsRequest.cs @@ -1,18 +1,13 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +public class UpdateBasketItemsRequest { + public string BasketId { get; set; } - public class UpdateBasketItemsRequest - { - public string BasketId { get; set; } - - public ICollection Updates { get; set; } + public ICollection Updates { get; set; } - public UpdateBasketItemsRequest() - { - Updates = new List(); - } + public UpdateBasketItemsRequest() + { + Updates = new List(); } - } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs index 070016f70..fa274a746 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequest.cs @@ -1,13 +1,8 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +public class UpdateBasketRequest { + public string BuyerId { get; set; } - public class UpdateBasketRequest - { - public string BuyerId { get; set; } - - public IEnumerable Items { get; set; } - } - + public IEnumerable Items { get; set; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs index 90800374d..6f48480b4 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Models/UpdateBasketRequestItemData.cs @@ -1,11 +1,10 @@ -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; + +public class UpdateBasketRequestItemData { - public class UpdateBasketRequestItemData - { - public string Id { get; set; } // Basket id + public string Id { get; set; } // Basket id - public int ProductId { get; set; } // Catalog item id + public int ProductId { get; set; } // Catalog item id - public int Quantity { get; set; } // Quantity - } + public int Quantity { get; set; } // Quantity } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs index 083292f54..70506fbda 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Program.cs @@ -1,9 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator; -using Serilog; - -BuildWebHost(args).Run(); +await BuildWebHost(args).RunAsync(); IWebHost BuildWebHost(string[] args) => WebHost diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs index 648a386c8..41d14d450 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs @@ -1,103 +1,95 @@ -using GrpcBasket; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public class BasketService : IBasketService { - public class BasketService : IBasketService + private readonly Basket.BasketClient _basketClient; + private readonly ILogger _logger; + + public BasketService(Basket.BasketClient basketClient, ILogger logger) + { + _basketClient = basketClient; + _logger = logger; + } + + public async Task GetByIdAsync(string id) { - private readonly Basket.BasketClient _basketClient; - private readonly ILogger _logger; + _logger.LogDebug("grpc client created, request = {@id}", id); + var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id }); + _logger.LogDebug("grpc response {@response}", response); - public BasketService(Basket.BasketClient basketClient, ILogger logger) - { - _basketClient = basketClient; - _logger = logger; - } + return MapToBasketData(response); + } + + public async Task UpdateAsync(BasketData currentBasket) + { + _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); + var request = MapToCustomerBasketRequest(currentBasket); + _logger.LogDebug("Grpc update basket request {@request}", request); + await _basketClient.UpdateBasketAsync(request); + } - public async Task GetById(string id) + private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) + { + if (customerBasketRequest == null) { - _logger.LogDebug("grpc client created, request = {@id}", id); - var response = await _basketClient.GetBasketByIdAsync(new BasketRequest { Id = id }); - _logger.LogDebug("grpc response {@response}", response); - - return MapToBasketData(response); + return null; } - public async Task UpdateAsync(BasketData currentBasket) + var map = new BasketData { - _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); - var request = MapToCustomerBasketRequest(currentBasket); - _logger.LogDebug("Grpc update basket request {@request}", request); + BuyerId = customerBasketRequest.Buyerid + }; - await _basketClient.UpdateBasketAsync(request); - } - - private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest) + customerBasketRequest.Items.ToList().ForEach(item => { - if (customerBasketRequest == null) + if (item.Id != null) { - return null; + map.Items.Add(new BasketDataItem + { + Id = item.Id, + OldUnitPrice = (decimal)item.Oldunitprice, + PictureUrl = item.Pictureurl, + ProductId = item.Productid, + ProductName = item.Productname, + Quantity = item.Quantity, + UnitPrice = (decimal)item.Unitprice + }); } + }); - var map = new BasketData - { - BuyerId = customerBasketRequest.Buyerid - }; - - customerBasketRequest.Items.ToList().ForEach(item => - { - if (item.Id != null) - { - map.Items.Add(new BasketDataItem - { - Id = item.Id, - OldUnitPrice = (decimal)item.Oldunitprice, - PictureUrl = item.Pictureurl, - ProductId = item.Productid, - ProductName = item.Productname, - Quantity = item.Quantity, - UnitPrice = (decimal)item.Unitprice - }); - } - }); + return map; + } - return map; + private CustomerBasketRequest MapToCustomerBasketRequest(BasketData basketData) + { + if (basketData == null) + { + return null; } - private CustomerBasketRequest MapToCustomerBasketRequest(BasketData basketData) + var map = new CustomerBasketRequest { - if (basketData == null) - { - return null; - } - - var map = new CustomerBasketRequest - { - Buyerid = basketData.BuyerId - }; + Buyerid = basketData.BuyerId + }; - basketData.Items.ToList().ForEach(item => + basketData.Items.ToList().ForEach(item => + { + if (item.Id != null) { - if (item.Id != null) + map.Items.Add(new BasketItemResponse { - map.Items.Add(new BasketItemResponse - { - Id = item.Id, - Oldunitprice = (double)item.OldUnitPrice, - Pictureurl = item.PictureUrl, - Productid = item.ProductId, - Productname = item.ProductName, - Quantity = item.Quantity, - Unitprice = (double)item.UnitPrice - }); - } - }); + Id = item.Id, + Oldunitprice = (double)item.OldUnitPrice, + Pictureurl = item.PictureUrl, + Productid = item.ProductId, + Productname = item.ProductName, + Quantity = item.Quantity, + Unitprice = (double)item.UnitPrice + }); + } + }); - return map; - } + return map; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs index f925954a6..3f7231aa3 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/CatalogService.cs @@ -1,52 +1,44 @@ -using CatalogApi; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public class CatalogService : ICatalogService { - public class CatalogService : ICatalogService - { - private readonly Catalog.CatalogClient _client; - private readonly ILogger _logger; + private readonly Catalog.CatalogClient _client; + private readonly ILogger _logger; - public CatalogService(Catalog.CatalogClient client, ILogger logger) - { - _client = client; - _logger = logger; - } + public CatalogService(Catalog.CatalogClient client, ILogger logger) + { + _client = client; + _logger = logger; + } - public async Task GetCatalogItemAsync(int id) - { - var request = new CatalogItemRequest { Id = id }; - _logger.LogInformation("grpc request {@request}", request); - var response = await _client.GetItemByIdAsync(request); - _logger.LogInformation("grpc response {@response}", response); - return MapToCatalogItemResponse(response); + public async Task GetCatalogItemAsync(int id) + { + var request = new CatalogItemRequest { Id = id }; + _logger.LogInformation("grpc request {@request}", request); + var response = await _client.GetItemByIdAsync(request); + _logger.LogInformation("grpc response {@response}", response); + return MapToCatalogItemResponse(response); - } + } - public async Task> GetCatalogItemsAsync(IEnumerable ids) - { - var request = new CatalogItemsRequest { Ids = string.Join(",", ids), PageIndex = 1, PageSize = 10 }; - _logger.LogInformation("grpc request {@request}", request); - var response = await _client.GetItemsByIdsAsync(request); - _logger.LogInformation("grpc response {@response}", response); - return response.Data.Select(this.MapToCatalogItemResponse); + public async Task> GetCatalogItemsAsync(IEnumerable ids) + { + var request = new CatalogItemsRequest { Ids = string.Join(",", ids), PageIndex = 1, PageSize = 10 }; + _logger.LogInformation("grpc request {@request}", request); + var response = await _client.GetItemsByIdsAsync(request); + _logger.LogInformation("grpc response {@response}", response); + return response.Data.Select(this.MapToCatalogItemResponse); - } + } - private CatalogItem MapToCatalogItemResponse(CatalogItemResponse catalogItemResponse) + private CatalogItem MapToCatalogItemResponse(CatalogItemResponse catalogItemResponse) + { + return new CatalogItem { - return new CatalogItem - { - Id = catalogItemResponse.Id, - Name = catalogItemResponse.Name, - PictureUri = catalogItemResponse.PictureUri, - Price = (decimal)catalogItemResponse.Price - }; - } + Id = catalogItemResponse.Id, + Name = catalogItemResponse.Name, + PictureUri = catalogItemResponse.PictureUri, + Price = (decimal)catalogItemResponse.Price + }; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs index fba539b7a..1049642d2 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IBasketService.cs @@ -1,12 +1,8 @@ -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public interface IBasketService { - public interface IBasketService - { - Task GetById(string id); + Task GetByIdAsync(string id); - Task UpdateAsync(BasketData currentBasket); - } + Task UpdateAsync(BasketData currentBasket); } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs index 9f86b84f9..7673a2706 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/ICatalogService.cs @@ -1,13 +1,8 @@ -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using System.Collections.Generic; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public interface ICatalogService { - public interface ICatalogService - { - Task GetCatalogItemAsync(int id); + Task GetCatalogItemAsync(int id); - Task> GetCatalogItemsAsync(IEnumerable ids); - } + Task> GetCatalogItemsAsync(IEnumerable ids); } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs index 0e972833c..989fc5fc0 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderApiClient.cs @@ -1,10 +1,6 @@ -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public interface IOrderApiClient { - public interface IOrderApiClient - { - Task GetOrderDraftFromBasketAsync(BasketData basket); - } + Task GetOrderDraftFromBasketAsync(BasketData basket); } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs index a20520747..6d21a7a87 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IOrderingService.cs @@ -1,10 +1,6 @@ -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public interface IOrderingService { - public interface IOrderingService - { - Task GetOrderDraftAsync(BasketData basketData); - } -} \ No newline at end of file + Task GetOrderDraftAsync(BasketData basketData); +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs index a26028d69..53fb65bb8 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderApiClient.cs @@ -1,37 +1,31 @@ -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System.Net.Http; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public class OrderApiClient : IOrderApiClient { - public class OrderApiClient : IOrderApiClient - { - private readonly HttpClient _apiClient; - private readonly ILogger _logger; - private readonly UrlsConfig _urls; + private readonly HttpClient _apiClient; + private readonly ILogger _logger; + private readonly UrlsConfig _urls; - public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config) - { - _apiClient = httpClient; - _logger = logger; - _urls = config.Value; - } + public OrderApiClient(HttpClient httpClient, ILogger logger, IOptions config) + { + _apiClient = httpClient; + _logger = logger; + _urls = config.Value; + } - public async Task GetOrderDraftFromBasketAsync(BasketData basket) - { - var url = _urls.Orders + UrlsConfig.OrdersOperations.GetOrderDraft(); - var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json"); - var response = await _apiClient.PostAsync(url, content); + public async Task GetOrderDraftFromBasketAsync(BasketData basket) + { + var url = $"{_urls.Orders}{UrlsConfig.OrdersOperations.GetOrderDraft()}"; + var content = new StringContent(JsonSerializer.Serialize(basket), System.Text.Encoding.UTF8, "application/json"); + var response = await _apiClient.PostAsync(url, content); - response.EnsureSuccessStatusCode(); + response.EnsureSuccessStatusCode(); - var ordersDraftResponse = await response.Content.ReadAsStringAsync(); + var ordersDraftResponse = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(ordersDraftResponse); - } + return JsonSerializer.Deserialize(ordersDraftResponse, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs index ab01b20f5..afa86b31b 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/OrderingService.cs @@ -1,79 +1,72 @@ -using GrpcOrdering; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Models; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +public class OrderingService : IOrderingService { - public class OrderingService : IOrderingService + private readonly OrderingGrpc.OrderingGrpcClient _orderingGrpcClient; + private readonly ILogger _logger; + + public OrderingService(OrderingGrpc.OrderingGrpcClient orderingGrpcClient, ILogger logger) { - private readonly OrderingGrpc.OrderingGrpcClient _orderingGrpcClient; - private readonly ILogger _logger; + _orderingGrpcClient = orderingGrpcClient; + _logger = logger; + } - public OrderingService(OrderingGrpc.OrderingGrpcClient orderingGrpcClient, ILogger logger) - { - _orderingGrpcClient = orderingGrpcClient; - _logger = logger; - } + public async Task GetOrderDraftAsync(BasketData basketData) + { + _logger.LogDebug(" grpc client created, basketData={@basketData}", basketData); - public async Task GetOrderDraftAsync(BasketData basketData) - { - _logger.LogDebug(" grpc client created, basketData={@basketData}", basketData); + var command = MapToOrderDraftCommand(basketData); + var response = await _orderingGrpcClient.CreateOrderDraftFromBasketDataAsync(command); + _logger.LogDebug(" grpc response: {@response}", response); - var command = MapToOrderDraftCommand(basketData); - var response = await _orderingGrpcClient.CreateOrderDraftFromBasketDataAsync(command); - _logger.LogDebug(" grpc response: {@response}", response); + return MapToResponse(response, basketData); + } - return MapToResponse(response, basketData); + private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft, BasketData basketData) + { + if (orderDraft == null) + { + return null; } - private OrderData MapToResponse(GrpcOrdering.OrderDraftDTO orderDraft, BasketData basketData) + var data = new OrderData { - if (orderDraft == null) - { - return null; - } + Buyer = basketData.BuyerId, + Total = (decimal)orderDraft.Total, + }; - var data = new OrderData - { - Buyer = basketData.BuyerId, - Total = (decimal)orderDraft.Total, - }; - - orderDraft.OrderItems.ToList().ForEach(o => data.OrderItems.Add(new OrderItemData - { - Discount = (decimal)o.Discount, - PictureUrl = o.PictureUrl, - ProductId = o.ProductId, - ProductName = o.ProductName, - UnitPrice = (decimal)o.UnitPrice, - Units = o.Units, - })); + orderDraft.OrderItems.ToList().ForEach(o => data.OrderItems.Add(new OrderItemData + { + Discount = (decimal)o.Discount, + PictureUrl = o.PictureUrl, + ProductId = o.ProductId, + ProductName = o.ProductName, + UnitPrice = (decimal)o.UnitPrice, + Units = o.Units, + })); - return data; - } + return data; + } - private CreateOrderDraftCommand MapToOrderDraftCommand(BasketData basketData) + private CreateOrderDraftCommand MapToOrderDraftCommand(BasketData basketData) + { + var command = new CreateOrderDraftCommand { - var command = new CreateOrderDraftCommand - { - BuyerId = basketData.BuyerId, - }; + BuyerId = basketData.BuyerId, + }; - basketData.Items.ForEach(i => command.Items.Add(new BasketItem - { - Id = i.Id, - OldUnitPrice = (double)i.OldUnitPrice, - PictureUrl = i.PictureUrl, - ProductId = i.ProductId, - ProductName = i.ProductName, - Quantity = i.Quantity, - UnitPrice = (double)i.UnitPrice, - })); - - return command; - } + basketData.Items.ForEach(i => command.Items.Add(new BasketItem + { + Id = i.Id, + OldUnitPrice = (double)i.OldUnitPrice, + PictureUrl = i.PictureUrl, + ProductId = i.ProductId, + ProductName = i.ProductName, + Quantity = i.Quantity, + UnitPrice = (double)i.UnitPrice, + })); + return command; } + } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs index 99780f66f..6e8e66931 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs @@ -1,225 +1,199 @@ -using CatalogApi; -using Devspaces.Support; -using GrpcBasket; -using GrpcOrdering; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Config; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure; -using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; - -namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddHealthChecks() + .AddCheck("self", () => HealthCheckResult.Healthy()) + .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) + .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) + .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) + .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) + .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }); + + services.AddCustomMvc(Configuration) + .AddCustomAuthentication(Configuration) + .AddDevspaces() + .AddApplicationServices() + .AddGrpcServices(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { - public Startup(IConfiguration configuration) + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) { - Configuration = configuration; + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); } - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) + if (env.IsDevelopment()) { - services.AddHealthChecks() - .AddCheck("self", () => HealthCheckResult.Healthy()) - .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) - .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) - .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) - .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) - .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }); - - services.AddCustomMvc(Configuration) - .AddCustomAuthentication(Configuration) - .AddDevspaces() - .AddApplicationServices() - .AddGrpcServices(); + app.UseDeveloperExceptionPage(); } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + app.UseHttpsRedirection(); + + app.UseSwagger().UseSwaggerUI(c => { - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) - { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); - app.UsePathBase(pathBase); - } + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } + c.OAuthClientId("webshoppingaggswaggerui"); + c.OAuthClientSecret(string.Empty); + c.OAuthRealm(string.Empty); + c.OAuthAppName("web shopping bff Swagger UI"); + }); - app.UseHttpsRedirection(); + app.UseRouting(); + app.UseCors("CorsPolicy"); + app.UseAuthentication(); + app.UseAuthorization(); - app.UseSwagger().UseSwaggerUI(c => + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); - - c.OAuthClientId("webshoppingaggswaggerui"); - c.OAuthClientSecret(string.Empty); - c.OAuthRealm(string.Empty); - c.OAuthAppName("web shopping bff Swagger UI"); + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); - - app.UseRouting(); - app.UseCors("CorsPolicy"); - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseEndpoints(endpoints => + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); + Predicate = r => r.Name.Contains("self") }); - } + }); } +} - public static class ServiceCollectionExtensions +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + + var identityUrl = configuration.GetValue("urls:identity"); + services.AddAuthentication(options => { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - var identityUrl = configuration.GetValue("urls:identity"); - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "webshoppingagg"; + }); - }) - .AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "webshoppingagg"; - }); + return services; + } - return services; - } + public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + services.Configure(configuration.GetSection("urls")); - public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) - { - services.AddOptions(); - services.Configure(configuration.GetSection("urls")); + services.AddControllers() + .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); - services.AddControllers() - .AddNewtonsoftJson(); + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); - services.AddSwaggerGen(options => + options.SwaggerDoc("v1", new OpenApiInfo { - options.DescribeAllEnumsAsStrings(); - - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "Shopping Aggregator for Web Clients", - Version = "v1", - Description = "Shopping Aggregator for Web Clients" - }); + Title = "Shopping Aggregator for Web Clients", + Version = "v1", + Description = "Shopping Aggregator for Web Clients" + }); - options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() + Implicit = new OpenApiOAuthFlow() { - Implicit = new OpenApiOAuthFlow() - { - AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), - TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), + AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), + TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), - Scopes = new Dictionary() - { - { "webshoppingagg", "Shopping Aggregator for Web Clients" } - } + Scopes = new Dictionary() + { + { "webshoppingagg", "Shopping Aggregator for Web Clients" } } } - }); - - options.OperationFilter(); + } }); - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .SetIsOriginAllowed((host) => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); + options.OperationFilter(); + }); - return services; - } - public static IServiceCollection AddApplicationServices(this IServiceCollection services) + services.AddCors(options => { - //register delegating handlers - services.AddTransient(); - services.AddSingleton(); + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } + public static IServiceCollection AddApplicationServices(this IServiceCollection services) + { + //register delegating handlers + services.AddTransient(); + services.AddSingleton(); - //register http services + //register http services - services.AddHttpClient() - .AddHttpMessageHandler() - .AddDevspacesSupport(); + services.AddHttpClient() + .AddHttpMessageHandler() + .AddDevspacesSupport(); - return services; - } + return services; + } - public static IServiceCollection AddGrpcServices(this IServiceCollection services) - { - services.AddTransient(); + public static IServiceCollection AddGrpcServices(this IServiceCollection services) + { + services.AddTransient(); - services.AddScoped(); + services.AddScoped(); - services.AddGrpcClient((services, options) => - { - var basketApi = services.GetRequiredService>().Value.GrpcBasket; - options.Address = new Uri(basketApi); - }).AddInterceptor(); + services.AddGrpcClient((services, options) => + { + var basketApi = services.GetRequiredService>().Value.GrpcBasket; + options.Address = new Uri(basketApi); + }).AddInterceptor(); - services.AddScoped(); + services.AddScoped(); - services.AddGrpcClient((services, options) => - { - var catalogApi = services.GetRequiredService>().Value.GrpcCatalog; - options.Address = new Uri(catalogApi); - }).AddInterceptor(); + services.AddGrpcClient((services, options) => + { + var catalogApi = services.GetRequiredService>().Value.GrpcCatalog; + options.Address = new Uri(catalogApi); + }).AddInterceptor(); - services.AddScoped(); + services.AddScoped(); - services.AddGrpcClient((services, options) => - { - var orderingApi = services.GetRequiredService>().Value.GrpcOrdering; - options.Address = new Uri(orderingApi); - }).AddInterceptor(); + services.AddGrpcClient((services, options) => + { + var orderingApi = services.GetRequiredService>().Value.GrpcOrdering; + options.Address = new Uri(orderingApi); + }).AddInterceptor(); - return services; - } + return services; } } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj index 2bae6e150..921d5b709 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj @@ -1,13 +1,12 @@  - net5.0 + net6.0 Web.Shopping.HttpAggregator Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator ..\..\..\docker-compose.dcproj false - true - preview + true @@ -17,20 +16,18 @@ - + - + - - diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json index 57c5afc34..055bcfc7f 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/appsettings.localhost.json @@ -1,6 +1,6 @@ { "urls": { - "basket": "http://localhost:55105", + "basket": "http://localhost:55103", "catalog": "http://localhost:55101", "orders": "http://localhost:55102", "identity": "http://localhost:55105", diff --git a/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj b/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj index 2ef353268..3398f17e6 100644 --- a/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj +++ b/src/BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj @@ -1,11 +1,11 @@  - net5.0 + net6.0 - - + + diff --git a/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs b/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs index 43dfa82f1..ac054693f 100644 --- a/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs +++ b/src/BuildingBlocks/Devspaces.Support/DevspacesMessageHandler.cs @@ -1,29 +1,22 @@ -using Microsoft.AspNetCore.Http; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; +namespace Devspaces.Support; -namespace Devspaces.Support +public class DevspacesMessageHandler : DelegatingHandler { - public class DevspacesMessageHandler : DelegatingHandler + private const string DevspacesHeaderName = "azds-route-as"; + private readonly IHttpContextAccessor _httpContextAccessor; + public DevspacesMessageHandler(IHttpContextAccessor httpContextAccessor) { - private const string DevspacesHeaderName = "azds-route-as"; - private readonly IHttpContextAccessor _httpContextAccessor; - public DevspacesMessageHandler(IHttpContextAccessor httpContextAccessor) - { - _httpContextAccessor = httpContextAccessor; - } + _httpContextAccessor = httpContextAccessor; + } - protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - var req = _httpContextAccessor.HttpContext.Request; + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var req = _httpContextAccessor.HttpContext.Request; - if (req.Headers.ContainsKey(DevspacesHeaderName)) - { - request.Headers.Add(DevspacesHeaderName, req.Headers[DevspacesHeaderName] as IEnumerable); - } - return base.SendAsync(request, cancellationToken); + if (req.Headers.ContainsKey(DevspacesHeaderName)) + { + request.Headers.Add(DevspacesHeaderName, req.Headers[DevspacesHeaderName] as IEnumerable); } + return base.SendAsync(request, cancellationToken); } } diff --git a/src/BuildingBlocks/Devspaces.Support/GlobalUsings.cs b/src/BuildingBlocks/Devspaces.Support/GlobalUsings.cs new file mode 100644 index 000000000..06c07e8fb --- /dev/null +++ b/src/BuildingBlocks/Devspaces.Support/GlobalUsings.cs @@ -0,0 +1,6 @@ +global using Microsoft.AspNetCore.Http; +global using Microsoft.Extensions.DependencyInjection; +global using System.Collections.Generic; +global using System.Net.Http; +global using System.Threading.Tasks; +global using System.Threading; diff --git a/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs b/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs index 00367b26c..fd78b9a40 100644 --- a/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs +++ b/src/BuildingBlocks/Devspaces.Support/HttpClientBuilderDevspacesExtensions.cs @@ -1,13 +1,10 @@ -using Microsoft.Extensions.DependencyInjection; +namespace Devspaces.Support; -namespace Devspaces.Support +public static class HttpClientBuilderDevspacesExtensions { - public static class HttpClientBuilderDevspacesExtensions + public static IHttpClientBuilder AddDevspacesSupport(this IHttpClientBuilder builder) { - public static IHttpClientBuilder AddDevspacesSupport(this IHttpClientBuilder builder) - { - builder.AddHttpMessageHandler(); - return builder; - } + builder.AddHttpMessageHandler(); + return builder; } } diff --git a/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs b/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs index d196c9184..15c3b1515 100644 --- a/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs +++ b/src/BuildingBlocks/Devspaces.Support/ServiceCollectionDevspacesExtensions.cs @@ -1,13 +1,10 @@ -using Microsoft.Extensions.DependencyInjection; +namespace Devspaces.Support; -namespace Devspaces.Support +public static class ServiceCollectionDevspacesExtensions { - public static class ServiceCollectionDevspacesExtensions + public static IServiceCollection AddDevspaces(this IServiceCollection services) { - public static IServiceCollection AddDevspaces(this IServiceCollection services) - { - services.AddTransient(); - return services; - } + services.AddTransient(); + return services; } } diff --git a/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj b/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj index a05d5157d..7b75841ec 100644 --- a/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj +++ b/src/BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj @@ -1,13 +1,16 @@  - netstandard2.1 + net6.0 - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/BuildingBlocks/EventBus/EventBus.Tests/TestIntegrationEvent.cs b/src/BuildingBlocks/EventBus/EventBus.Tests/TestIntegrationEvent.cs index a77f3ef6f..4e85e7ae6 100644 --- a/src/BuildingBlocks/EventBus/EventBus.Tests/TestIntegrationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus.Tests/TestIntegrationEvent.cs @@ -5,7 +5,7 @@ using System.Text; namespace EventBus.Tests { - public class TestIntegrationEvent : IntegrationEvent + public record TestIntegrationEvent : IntegrationEvent { } } diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IDynamicIntegrationEventHandler.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IDynamicIntegrationEventHandler.cs index c26ee6a81..8b9fbe497 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IDynamicIntegrationEventHandler.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IDynamicIntegrationEventHandler.cs @@ -1,9 +1,6 @@ -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions +public interface IDynamicIntegrationEventHandler { - public interface IDynamicIntegrationEventHandler - { - Task Handle(dynamic eventData); - } + Task Handle(dynamic eventData); } diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs index 4c9758a40..492a10e42 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IEventBus.cs @@ -1,23 +1,20 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions +public interface IEventBus { - public interface IEventBus - { - void Publish(IntegrationEvent @event); + void Publish(IntegrationEvent @event); - void Subscribe() - where T : IntegrationEvent - where TH : IIntegrationEventHandler; + void Subscribe() + where T : IntegrationEvent + where TH : IIntegrationEventHandler; - void SubscribeDynamic(string eventName) - where TH : IDynamicIntegrationEventHandler; + void SubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler; - void UnsubscribeDynamic(string eventName) - where TH : IDynamicIntegrationEventHandler; + void UnsubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler; - void Unsubscribe() - where TH : IIntegrationEventHandler - where T : IntegrationEvent; - } + void Unsubscribe() + where TH : IIntegrationEventHandler + where T : IntegrationEvent; } diff --git a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs index 99735b871..030c604b5 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Abstractions/IIntegrationEventHandler.cs @@ -1,15 +1,11 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions +public interface IIntegrationEventHandler : IIntegrationEventHandler + where TIntegrationEvent : IntegrationEvent { - public interface IIntegrationEventHandler : IIntegrationEventHandler - where TIntegrationEvent : IntegrationEvent - { - Task Handle(TIntegrationEvent @event); - } + Task Handle(TIntegrationEvent @event); +} - public interface IIntegrationEventHandler - { - } +public interface IIntegrationEventHandler +{ } diff --git a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj index 8db6db3b5..37396d3ec 100644 --- a/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBus/EventBus.csproj @@ -1,12 +1,11 @@  - net5.0 + net6.0 Microsoft.eShopOnContainers.BuildingBlocks.EventBus - - + \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs index 201dcf6b5..31118c4da 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Events/IntegrationEvent.cs @@ -1,27 +1,23 @@ -using Newtonsoft.Json; -using System; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events -{ - public record IntegrationEvent +public record IntegrationEvent +{ + public IntegrationEvent() { - public IntegrationEvent() - { - Id = Guid.NewGuid(); - CreationDate = DateTime.UtcNow; - } + Id = Guid.NewGuid(); + CreationDate = DateTime.UtcNow; + } - [JsonConstructor] - public IntegrationEvent(Guid id, DateTime createDate) - { - Id = id; - CreationDate = createDate; - } + [JsonConstructor] + public IntegrationEvent(Guid id, DateTime createDate) + { + Id = id; + CreationDate = createDate; + } - [JsonProperty] - public Guid Id { get; private init; } + [JsonInclude] + public Guid Id { get; private init; } - [JsonProperty] - public DateTime CreationDate { get; private init; } - } + [JsonInclude] + public DateTime CreationDate { get; private init; } } diff --git a/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs b/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs index 775c29c3e..70e295beb 100644 --- a/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs +++ b/src/BuildingBlocks/EventBus/EventBus/Extensions/GenericTypeExtensions.cs @@ -1,30 +1,26 @@ -using System; -using System.Linq; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions +public static class GenericTypeExtensions { - public static class GenericTypeExtensions + public static string GetGenericTypeName(this Type type) { - public static string GetGenericTypeName(this Type type) - { - var typeName = string.Empty; - - if (type.IsGenericType) - { - var genericTypes = string.Join(",", type.GetGenericArguments().Select(t => t.Name).ToArray()); - typeName = $"{type.Name.Remove(type.Name.IndexOf('`'))}<{genericTypes}>"; - } - else - { - typeName = type.Name; - } + var typeName = string.Empty; - return typeName; + if (type.IsGenericType) + { + var genericTypes = string.Join(",", type.GetGenericArguments().Select(t => t.Name).ToArray()); + typeName = $"{type.Name.Remove(type.Name.IndexOf('`'))}<{genericTypes}>"; } - - public static string GetGenericTypeName(this object @object) + else { - return @object.GetType().GetGenericTypeName(); + typeName = type.Name; } + + return typeName; + } + + public static string GetGenericTypeName(this object @object) + { + return @object.GetType().GetGenericTypeName(); } } diff --git a/src/BuildingBlocks/EventBus/EventBus/GlobalUsings.cs b/src/BuildingBlocks/EventBus/EventBus/GlobalUsings.cs new file mode 100644 index 000000000..faddc5a13 --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBus/GlobalUsings.cs @@ -0,0 +1,8 @@ +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using static Microsoft.eShopOnContainers.BuildingBlocks.EventBus.InMemoryEventBusSubscriptionsManager; +global using System.Collections.Generic; +global using System.Linq; +global using System.Text.Json.Serialization; +global using System.Threading.Tasks; +global using System; diff --git a/src/BuildingBlocks/EventBus/EventBus/IEventBusSubscriptionsManager.cs b/src/BuildingBlocks/EventBus/EventBus/IEventBusSubscriptionsManager.cs index c83c505b1..a140bfc75 100644 --- a/src/BuildingBlocks/EventBus/EventBus/IEventBusSubscriptionsManager.cs +++ b/src/BuildingBlocks/EventBus/EventBus/IEventBusSubscriptionsManager.cs @@ -1,34 +1,27 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using static Microsoft.eShopOnContainers.BuildingBlocks.EventBus.InMemoryEventBusSubscriptionsManager; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus +public interface IEventBusSubscriptionsManager { - public interface IEventBusSubscriptionsManager - { - bool IsEmpty { get; } - event EventHandler OnEventRemoved; - void AddDynamicSubscription(string eventName) - where TH : IDynamicIntegrationEventHandler; + bool IsEmpty { get; } + event EventHandler OnEventRemoved; + void AddDynamicSubscription(string eventName) + where TH : IDynamicIntegrationEventHandler; - void AddSubscription() - where T : IntegrationEvent - where TH : IIntegrationEventHandler; + void AddSubscription() + where T : IntegrationEvent + where TH : IIntegrationEventHandler; - void RemoveSubscription() - where TH : IIntegrationEventHandler - where T : IntegrationEvent; - void RemoveDynamicSubscription(string eventName) - where TH : IDynamicIntegrationEventHandler; + void RemoveSubscription() + where TH : IIntegrationEventHandler + where T : IntegrationEvent; + void RemoveDynamicSubscription(string eventName) + where TH : IDynamicIntegrationEventHandler; - bool HasSubscriptionsForEvent() where T : IntegrationEvent; - bool HasSubscriptionsForEvent(string eventName); - Type GetEventTypeByName(string eventName); - void Clear(); - IEnumerable GetHandlersForEvent() where T : IntegrationEvent; - IEnumerable GetHandlersForEvent(string eventName); - string GetEventKey(); - } -} \ No newline at end of file + bool HasSubscriptionsForEvent() where T : IntegrationEvent; + bool HasSubscriptionsForEvent(string eventName); + Type GetEventTypeByName(string eventName); + void Clear(); + IEnumerable GetHandlersForEvent() where T : IntegrationEvent; + IEnumerable GetHandlersForEvent(string eventName); + string GetEventKey(); +} diff --git a/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs b/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs index a86248f01..5de35b292 100644 --- a/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs +++ b/src/BuildingBlocks/EventBus/EventBus/InMemoryEventBusSubscriptionsManager.cs @@ -1,162 +1,155 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus +public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager { - public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager + + + private readonly Dictionary> _handlers; + private readonly List _eventTypes; + + public event EventHandler OnEventRemoved; + + public InMemoryEventBusSubscriptionsManager() { + _handlers = new Dictionary>(); + _eventTypes = new List(); + } + public bool IsEmpty => _handlers is { Count: 0 }; + public void Clear() => _handlers.Clear(); - private readonly Dictionary> _handlers; - private readonly List _eventTypes; + public void AddDynamicSubscription(string eventName) + where TH : IDynamicIntegrationEventHandler + { + DoAddSubscription(typeof(TH), eventName, isDynamic: true); + } - public event EventHandler OnEventRemoved; + public void AddSubscription() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = GetEventKey(); - public InMemoryEventBusSubscriptionsManager() + DoAddSubscription(typeof(TH), eventName, isDynamic: false); + + if (!_eventTypes.Contains(typeof(T))) { - _handlers = new Dictionary>(); - _eventTypes = new List(); + _eventTypes.Add(typeof(T)); } + } - public bool IsEmpty => !_handlers.Keys.Any(); - public void Clear() => _handlers.Clear(); - - public void AddDynamicSubscription(string eventName) - where TH : IDynamicIntegrationEventHandler + private void DoAddSubscription(Type handlerType, string eventName, bool isDynamic) + { + if (!HasSubscriptionsForEvent(eventName)) { - DoAddSubscription(typeof(TH), eventName, isDynamic: true); + _handlers.Add(eventName, new List()); } - public void AddSubscription() - where T : IntegrationEvent - where TH : IIntegrationEventHandler + if (_handlers[eventName].Any(s => s.HandlerType == handlerType)) { - var eventName = GetEventKey(); - - DoAddSubscription(typeof(TH), eventName, isDynamic: false); - - if (!_eventTypes.Contains(typeof(T))) - { - _eventTypes.Add(typeof(T)); - } + throw new ArgumentException( + $"Handler Type {handlerType.Name} already registered for '{eventName}'", nameof(handlerType)); } - private void DoAddSubscription(Type handlerType, string eventName, bool isDynamic) + if (isDynamic) { - if (!HasSubscriptionsForEvent(eventName)) - { - _handlers.Add(eventName, new List()); - } - - if (_handlers[eventName].Any(s => s.HandlerType == handlerType)) - { - throw new ArgumentException( - $"Handler Type {handlerType.Name} already registered for '{eventName}'", nameof(handlerType)); - } - - if (isDynamic) - { - _handlers[eventName].Add(SubscriptionInfo.Dynamic(handlerType)); - } - else - { - _handlers[eventName].Add(SubscriptionInfo.Typed(handlerType)); - } + _handlers[eventName].Add(SubscriptionInfo.Dynamic(handlerType)); } - - - public void RemoveDynamicSubscription(string eventName) - where TH : IDynamicIntegrationEventHandler + else { - var handlerToRemove = FindDynamicSubscriptionToRemove(eventName); - DoRemoveHandler(eventName, handlerToRemove); + _handlers[eventName].Add(SubscriptionInfo.Typed(handlerType)); } + } - public void RemoveSubscription() - where TH : IIntegrationEventHandler - where T : IntegrationEvent - { - var handlerToRemove = FindSubscriptionToRemove(); - var eventName = GetEventKey(); - DoRemoveHandler(eventName, handlerToRemove); - } + public void RemoveDynamicSubscription(string eventName) + where TH : IDynamicIntegrationEventHandler + { + var handlerToRemove = FindDynamicSubscriptionToRemove(eventName); + DoRemoveHandler(eventName, handlerToRemove); + } + + + public void RemoveSubscription() + where TH : IIntegrationEventHandler + where T : IntegrationEvent + { + var handlerToRemove = FindSubscriptionToRemove(); + var eventName = GetEventKey(); + DoRemoveHandler(eventName, handlerToRemove); + } - private void DoRemoveHandler(string eventName, SubscriptionInfo subsToRemove) + private void DoRemoveHandler(string eventName, SubscriptionInfo subsToRemove) + { + if (subsToRemove != null) { - if (subsToRemove != null) + _handlers[eventName].Remove(subsToRemove); + if (!_handlers[eventName].Any()) { - _handlers[eventName].Remove(subsToRemove); - if (!_handlers[eventName].Any()) + _handlers.Remove(eventName); + var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); + if (eventType != null) { - _handlers.Remove(eventName); - var eventType = _eventTypes.SingleOrDefault(e => e.Name == eventName); - if (eventType != null) - { - _eventTypes.Remove(eventType); - } - RaiseOnEventRemoved(eventName); + _eventTypes.Remove(eventType); } - + RaiseOnEventRemoved(eventName); } - } - public IEnumerable GetHandlersForEvent() where T : IntegrationEvent - { - var key = GetEventKey(); - return GetHandlersForEvent(key); } - public IEnumerable GetHandlersForEvent(string eventName) => _handlers[eventName]; + } - private void RaiseOnEventRemoved(string eventName) - { - var handler = OnEventRemoved; - handler?.Invoke(this, eventName); - } + public IEnumerable GetHandlersForEvent() where T : IntegrationEvent + { + var key = GetEventKey(); + return GetHandlersForEvent(key); + } + public IEnumerable GetHandlersForEvent(string eventName) => _handlers[eventName]; + private void RaiseOnEventRemoved(string eventName) + { + var handler = OnEventRemoved; + handler?.Invoke(this, eventName); + } - private SubscriptionInfo FindDynamicSubscriptionToRemove(string eventName) - where TH : IDynamicIntegrationEventHandler - { - return DoFindSubscriptionToRemove(eventName, typeof(TH)); - } + private SubscriptionInfo FindDynamicSubscriptionToRemove(string eventName) + where TH : IDynamicIntegrationEventHandler + { + return DoFindSubscriptionToRemove(eventName, typeof(TH)); + } - private SubscriptionInfo FindSubscriptionToRemove() - where T : IntegrationEvent - where TH : IIntegrationEventHandler - { - var eventName = GetEventKey(); - return DoFindSubscriptionToRemove(eventName, typeof(TH)); - } - private SubscriptionInfo DoFindSubscriptionToRemove(string eventName, Type handlerType) + private SubscriptionInfo FindSubscriptionToRemove() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = GetEventKey(); + return DoFindSubscriptionToRemove(eventName, typeof(TH)); + } + + private SubscriptionInfo DoFindSubscriptionToRemove(string eventName, Type handlerType) + { + if (!HasSubscriptionsForEvent(eventName)) { - if (!HasSubscriptionsForEvent(eventName)) - { - return null; - } + return null; + } - return _handlers[eventName].SingleOrDefault(s => s.HandlerType == handlerType); + return _handlers[eventName].SingleOrDefault(s => s.HandlerType == handlerType); - } + } - public bool HasSubscriptionsForEvent() where T : IntegrationEvent - { - var key = GetEventKey(); - return HasSubscriptionsForEvent(key); - } - public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName); + public bool HasSubscriptionsForEvent() where T : IntegrationEvent + { + var key = GetEventKey(); + return HasSubscriptionsForEvent(key); + } + public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName); - public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); + public Type GetEventTypeByName(string eventName) => _eventTypes.SingleOrDefault(t => t.Name == eventName); - public string GetEventKey() - { - return typeof(T).Name; - } + public string GetEventKey() + { + return typeof(T).Name; } } diff --git a/src/BuildingBlocks/EventBus/EventBus/SubscriptionInfo.cs b/src/BuildingBlocks/EventBus/EventBus/SubscriptionInfo.cs index 9e61034a0..17e29d965 100644 --- a/src/BuildingBlocks/EventBus/EventBus/SubscriptionInfo.cs +++ b/src/BuildingBlocks/EventBus/EventBus/SubscriptionInfo.cs @@ -1,28 +1,22 @@ -using System; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBus +public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager { - public partial class InMemoryEventBusSubscriptionsManager : IEventBusSubscriptionsManager + public class SubscriptionInfo { - public class SubscriptionInfo + public bool IsDynamic { get; } + public Type HandlerType { get; } + + private SubscriptionInfo(bool isDynamic, Type handlerType) { - public bool IsDynamic { get; } - public Type HandlerType { get; } + IsDynamic = isDynamic; + HandlerType = handlerType; + } - private SubscriptionInfo(bool isDynamic, Type handlerType) - { - IsDynamic = isDynamic; - HandlerType = handlerType; - } + public static SubscriptionInfo Dynamic(Type handlerType) => + new SubscriptionInfo(true, handlerType); - public static SubscriptionInfo Dynamic(Type handlerType) - { - return new SubscriptionInfo(true, handlerType); - } - public static SubscriptionInfo Typed(Type handlerType) - { - return new SubscriptionInfo(false, handlerType); - } - } + public static SubscriptionInfo Typed(Type handlerType) => + new SubscriptionInfo(false, handlerType); } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs index 93e5b2917..17fdba7da 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/DefaultRabbitMQPersistentConnection.cs @@ -1,131 +1,123 @@ -using Microsoft.Extensions.Logging; -using Polly; -using Polly.Retry; -using RabbitMQ.Client; -using RabbitMQ.Client.Events; -using RabbitMQ.Client.Exceptions; -using System; -using System.IO; -using System.Net.Sockets; - -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; + +public class DefaultRabbitMQPersistentConnection + : IRabbitMQPersistentConnection { - public class DefaultRabbitMQPersistentConnection - : IRabbitMQPersistentConnection - { - private readonly IConnectionFactory _connectionFactory; - private readonly ILogger _logger; - private readonly int _retryCount; - IConnection _connection; - bool _disposed; + private readonly IConnectionFactory _connectionFactory; + private readonly ILogger _logger; + private readonly int _retryCount; + IConnection _connection; + bool _disposed; - object sync_root = new object(); + object sync_root = new object(); - public DefaultRabbitMQPersistentConnection(IConnectionFactory connectionFactory, ILogger logger, int retryCount = 5) - { - _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _retryCount = retryCount; - } + public DefaultRabbitMQPersistentConnection(IConnectionFactory connectionFactory, ILogger logger, int retryCount = 5) + { + _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _retryCount = retryCount; + } - public bool IsConnected + public bool IsConnected + { + get { - get - { - return _connection != null && _connection.IsOpen && !_disposed; - } + return _connection != null && _connection.IsOpen && !_disposed; } + } - public IModel CreateModel() + public IModel CreateModel() + { + if (!IsConnected) { - if (!IsConnected) - { - throw new InvalidOperationException("No RabbitMQ connections are available to perform this action"); - } - - return _connection.CreateModel(); + throw new InvalidOperationException("No RabbitMQ connections are available to perform this action"); } - public void Dispose() - { - if (_disposed) return; + return _connection.CreateModel(); + } - _disposed = true; + public void Dispose() + { + if (_disposed) return; - try - { - _connection.Dispose(); - } - catch (IOException ex) - { - _logger.LogCritical(ex.ToString()); - } + _disposed = true; + + try + { + _connection.ConnectionShutdown -= OnConnectionShutdown; + _connection.CallbackException -= OnCallbackException; + _connection.ConnectionBlocked -= OnConnectionBlocked; + _connection.Dispose(); + } + catch (IOException ex) + { + _logger.LogCritical(ex.ToString()); } + } + + public bool TryConnect() + { + _logger.LogInformation("RabbitMQ Client is trying to connect"); - public bool TryConnect() + lock (sync_root) { - _logger.LogInformation("RabbitMQ Client is trying to connect"); + var policy = RetryPolicy.Handle() + .Or() + .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => + { + _logger.LogWarning(ex, "RabbitMQ Client could not connect after {TimeOut}s ({ExceptionMessage})", $"{time.TotalSeconds:n1}", ex.Message); + } + ); - lock (sync_root) + policy.Execute(() => { - var policy = RetryPolicy.Handle() - .Or() - .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => - { - _logger.LogWarning(ex, "RabbitMQ Client could not connect after {TimeOut}s ({ExceptionMessage})", $"{time.TotalSeconds:n1}", ex.Message); - } - ); - - policy.Execute(() => - { - _connection = _connectionFactory - .CreateConnection(); - }); + _connection = _connectionFactory + .CreateConnection(); + }); - if (IsConnected) - { - _connection.ConnectionShutdown += OnConnectionShutdown; - _connection.CallbackException += OnCallbackException; - _connection.ConnectionBlocked += OnConnectionBlocked; + if (IsConnected) + { + _connection.ConnectionShutdown += OnConnectionShutdown; + _connection.CallbackException += OnCallbackException; + _connection.ConnectionBlocked += OnConnectionBlocked; - _logger.LogInformation("RabbitMQ Client acquired a persistent connection to '{HostName}' and is subscribed to failure events", _connection.Endpoint.HostName); + _logger.LogInformation("RabbitMQ Client acquired a persistent connection to '{HostName}' and is subscribed to failure events", _connection.Endpoint.HostName); - return true; - } - else - { - _logger.LogCritical("FATAL ERROR: RabbitMQ connections could not be created and opened"); + return true; + } + else + { + _logger.LogCritical("FATAL ERROR: RabbitMQ connections could not be created and opened"); - return false; - } + return false; } } + } - private void OnConnectionBlocked(object sender, ConnectionBlockedEventArgs e) - { - if (_disposed) return; + private void OnConnectionBlocked(object sender, ConnectionBlockedEventArgs e) + { + if (_disposed) return; - _logger.LogWarning("A RabbitMQ connection is shutdown. Trying to re-connect..."); + _logger.LogWarning("A RabbitMQ connection is shutdown. Trying to re-connect..."); - TryConnect(); - } + TryConnect(); + } - void OnCallbackException(object sender, CallbackExceptionEventArgs e) - { - if (_disposed) return; + void OnCallbackException(object sender, CallbackExceptionEventArgs e) + { + if (_disposed) return; - _logger.LogWarning("A RabbitMQ connection throw exception. Trying to re-connect..."); + _logger.LogWarning("A RabbitMQ connection throw exception. Trying to re-connect..."); - TryConnect(); - } + TryConnect(); + } - void OnConnectionShutdown(object sender, ShutdownEventArgs reason) - { - if (_disposed) return; + void OnConnectionShutdown(object sender, ShutdownEventArgs reason) + { + if (_disposed) return; - _logger.LogWarning("A RabbitMQ connection is on shutdown. Trying to re-connect..."); + _logger.LogWarning("A RabbitMQ connection is on shutdown. Trying to re-connect..."); - TryConnect(); - } + TryConnect(); } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 50bd97bc9..31f85a339 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -1,300 +1,272 @@ -using Autofac; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Polly; -using Polly.Retry; -using RabbitMQ.Client; -using RabbitMQ.Client.Events; -using RabbitMQ.Client.Exceptions; -using System; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; + +public class EventBusRabbitMQ : IEventBus, IDisposable { - public class EventBusRabbitMQ : IEventBus, IDisposable - { - const string BROKER_NAME = "eshop_event_bus"; - const string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; + const string BROKER_NAME = "eshop_event_bus"; + const string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; - private readonly IRabbitMQPersistentConnection _persistentConnection; - private readonly ILogger _logger; - private readonly IEventBusSubscriptionsManager _subsManager; - private readonly ILifetimeScope _autofac; - private readonly int _retryCount; + private readonly IRabbitMQPersistentConnection _persistentConnection; + private readonly ILogger _logger; + private readonly IEventBusSubscriptionsManager _subsManager; + private readonly ILifetimeScope _autofac; + private readonly int _retryCount; - private IModel _consumerChannel; - private string _queueName; + private IModel _consumerChannel; + private string _queueName; - public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger logger, - ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null, int retryCount = 5) - { - _persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); - _queueName = queueName; - _consumerChannel = CreateConsumerChannel(); - _autofac = autofac; - _retryCount = retryCount; - _subsManager.OnEventRemoved += SubsManager_OnEventRemoved; - } + public EventBusRabbitMQ(IRabbitMQPersistentConnection persistentConnection, ILogger logger, + ILifetimeScope autofac, IEventBusSubscriptionsManager subsManager, string queueName = null, int retryCount = 5) + { + _persistentConnection = persistentConnection ?? throw new ArgumentNullException(nameof(persistentConnection)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); + _queueName = queueName; + _consumerChannel = CreateConsumerChannel(); + _autofac = autofac; + _retryCount = retryCount; + _subsManager.OnEventRemoved += SubsManager_OnEventRemoved; + } - private void SubsManager_OnEventRemoved(object sender, string eventName) + private void SubsManager_OnEventRemoved(object sender, string eventName) + { + if (!_persistentConnection.IsConnected) { - if (!_persistentConnection.IsConnected) - { - _persistentConnection.TryConnect(); - } + _persistentConnection.TryConnect(); + } - using (var channel = _persistentConnection.CreateModel()) - { - channel.QueueUnbind(queue: _queueName, - exchange: BROKER_NAME, - routingKey: eventName); + using var channel = _persistentConnection.CreateModel(); + channel.QueueUnbind(queue: _queueName, + exchange: BROKER_NAME, + routingKey: eventName); - if (_subsManager.IsEmpty) - { - _queueName = string.Empty; - _consumerChannel.Close(); - } - } + if (_subsManager.IsEmpty) + { + _queueName = string.Empty; + _consumerChannel.Close(); } + } - public void Publish(IntegrationEvent @event) + public void Publish(IntegrationEvent @event) + { + if (!_persistentConnection.IsConnected) { - if (!_persistentConnection.IsConnected) - { - _persistentConnection.TryConnect(); - } - - var policy = RetryPolicy.Handle() - .Or() - .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => - { - _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message); - }); + _persistentConnection.TryConnect(); + } - var eventName = @event.GetType().Name; + var policy = RetryPolicy.Handle() + .Or() + .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) => + { + _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message); + }); - _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); + var eventName = @event.GetType().Name; - using (var channel = _persistentConnection.CreateModel()) - { - _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); + _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); - channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); + using var channel = _persistentConnection.CreateModel(); + _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); - var message = JsonConvert.SerializeObject(@event); - var body = Encoding.UTF8.GetBytes(message); + channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); - policy.Execute(() => - { - var properties = channel.CreateBasicProperties(); - properties.DeliveryMode = 2; // persistent - - _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id); - - channel.BasicPublish( - exchange: BROKER_NAME, - routingKey: eventName, - mandatory: true, - basicProperties: properties, - body: body); - }); - } - } + var body = JsonSerializer.SerializeToUtf8Bytes(@event, @event.GetType(), new JsonSerializerOptions + { + WriteIndented = true + }); - public void SubscribeDynamic(string eventName) - where TH : IDynamicIntegrationEventHandler + policy.Execute(() => { - _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName()); + var properties = channel.CreateBasicProperties(); + properties.DeliveryMode = 2; // persistent + + _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id); + + channel.BasicPublish( + exchange: BROKER_NAME, + routingKey: eventName, + mandatory: true, + basicProperties: properties, + body: body); + }); + } - DoInternalSubscription(eventName); - _subsManager.AddDynamicSubscription(eventName); - StartBasicConsume(); - } + public void SubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler + { + _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName()); - public void Subscribe() - where T : IntegrationEvent - where TH : IIntegrationEventHandler - { - var eventName = _subsManager.GetEventKey(); - DoInternalSubscription(eventName); + DoInternalSubscription(eventName); + _subsManager.AddDynamicSubscription(eventName); + StartBasicConsume(); + } + + public void Subscribe() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = _subsManager.GetEventKey(); + DoInternalSubscription(eventName); - _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName()); + _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName()); - _subsManager.AddSubscription(); - StartBasicConsume(); - } + _subsManager.AddSubscription(); + StartBasicConsume(); + } - private void DoInternalSubscription(string eventName) + private void DoInternalSubscription(string eventName) + { + var containsKey = _subsManager.HasSubscriptionsForEvent(eventName); + if (!containsKey) { - var containsKey = _subsManager.HasSubscriptionsForEvent(eventName); - if (!containsKey) + if (!_persistentConnection.IsConnected) { - if (!_persistentConnection.IsConnected) - { - _persistentConnection.TryConnect(); - } - - using (var channel = _persistentConnection.CreateModel()) - { - channel.QueueBind(queue: _queueName, - exchange: BROKER_NAME, - routingKey: eventName); - } + _persistentConnection.TryConnect(); } + + _consumerChannel.QueueBind(queue: _queueName, + exchange: BROKER_NAME, + routingKey: eventName); } + } - public void Unsubscribe() - where T : IntegrationEvent - where TH : IIntegrationEventHandler - { - var eventName = _subsManager.GetEventKey(); + public void Unsubscribe() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = _subsManager.GetEventKey(); - _logger.LogInformation("Unsubscribing from event {EventName}", eventName); + _logger.LogInformation("Unsubscribing from event {EventName}", eventName); - _subsManager.RemoveSubscription(); - } + _subsManager.RemoveSubscription(); + } + + public void UnsubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler + { + _subsManager.RemoveDynamicSubscription(eventName); + } - public void UnsubscribeDynamic(string eventName) - where TH : IDynamicIntegrationEventHandler + public void Dispose() + { + if (_consumerChannel != null) { - _subsManager.RemoveDynamicSubscription(eventName); + _consumerChannel.Dispose(); } - public void Dispose() - { - if (_consumerChannel != null) - { - _consumerChannel.Dispose(); - } + _subsManager.Clear(); + } - _subsManager.Clear(); - } + private void StartBasicConsume() + { + _logger.LogTrace("Starting RabbitMQ basic consume"); - private void StartBasicConsume() + if (_consumerChannel != null) { - _logger.LogTrace("Starting RabbitMQ basic consume"); + var consumer = new AsyncEventingBasicConsumer(_consumerChannel); - if (_consumerChannel != null) - { - var consumer = new AsyncEventingBasicConsumer(_consumerChannel); - - consumer.Received += Consumer_Received; + consumer.Received += Consumer_Received; - _consumerChannel.BasicConsume( - queue: _queueName, - autoAck: false, - consumer: consumer); - } - else - { - _logger.LogError("StartBasicConsume can't call on _consumerChannel == null"); - } + _consumerChannel.BasicConsume( + queue: _queueName, + autoAck: false, + consumer: consumer); } - - private async Task Consumer_Received(object sender, BasicDeliverEventArgs eventArgs) + else { - var eventName = eventArgs.RoutingKey; - var message = Encoding.UTF8.GetString(eventArgs.Body.Span); + _logger.LogError("StartBasicConsume can't call on _consumerChannel == null"); + } + } - try - { - if (message.ToLowerInvariant().Contains("throw-fake-exception")) - { - throw new InvalidOperationException($"Fake exception requested: \"{message}\""); - } + private async Task Consumer_Received(object sender, BasicDeliverEventArgs eventArgs) + { + var eventName = eventArgs.RoutingKey; + var message = Encoding.UTF8.GetString(eventArgs.Body.Span); - await ProcessEvent(eventName, message); - } - catch (Exception ex) + try + { + if (message.ToLowerInvariant().Contains("throw-fake-exception")) { - _logger.LogWarning(ex, "----- ERROR Processing message \"{Message}\"", message); + throw new InvalidOperationException($"Fake exception requested: \"{message}\""); } - // Even on exception we take the message off the queue. - // in a REAL WORLD app this should be handled with a Dead Letter Exchange (DLX). - // For more information see: https://www.rabbitmq.com/dlx.html - _consumerChannel.BasicAck(eventArgs.DeliveryTag, multiple: false); + await ProcessEvent(eventName, message); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "----- ERROR Processing message \"{Message}\"", message); } - private IModel CreateConsumerChannel() + // Even on exception we take the message off the queue. + // in a REAL WORLD app this should be handled with a Dead Letter Exchange (DLX). + // For more information see: https://www.rabbitmq.com/dlx.html + _consumerChannel.BasicAck(eventArgs.DeliveryTag, multiple: false); + } + + private IModel CreateConsumerChannel() + { + if (!_persistentConnection.IsConnected) { - if (!_persistentConnection.IsConnected) - { - _persistentConnection.TryConnect(); - } + _persistentConnection.TryConnect(); + } - _logger.LogTrace("Creating RabbitMQ consumer channel"); + _logger.LogTrace("Creating RabbitMQ consumer channel"); - var channel = _persistentConnection.CreateModel(); + var channel = _persistentConnection.CreateModel(); - channel.ExchangeDeclare(exchange: BROKER_NAME, - type: "direct"); + channel.ExchangeDeclare(exchange: BROKER_NAME, + type: "direct"); - channel.QueueDeclare(queue: _queueName, - durable: true, - exclusive: false, - autoDelete: false, - arguments: null); + channel.QueueDeclare(queue: _queueName, + durable: true, + exclusive: false, + autoDelete: false, + arguments: null); - channel.CallbackException += (sender, ea) => - { - _logger.LogWarning(ea.Exception, "Recreating RabbitMQ consumer channel"); + channel.CallbackException += (sender, ea) => + { + _logger.LogWarning(ea.Exception, "Recreating RabbitMQ consumer channel"); - _consumerChannel.Dispose(); - _consumerChannel = CreateConsumerChannel(); - StartBasicConsume(); - }; + _consumerChannel.Dispose(); + _consumerChannel = CreateConsumerChannel(); + StartBasicConsume(); + }; - return channel; - } + return channel; + } - private async Task ProcessEvent(string eventName, string message) - { - _logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName); + private async Task ProcessEvent(string eventName, string message) + { + _logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName); - if (_subsManager.HasSubscriptionsForEvent(eventName)) + if (_subsManager.HasSubscriptionsForEvent(eventName)) + { + using var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME); + var subscriptions = _subsManager.GetHandlersForEvent(eventName); + foreach (var subscription in subscriptions) { - using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) + if (subscription.IsDynamic) { - var subscriptions = _subsManager.GetHandlersForEvent(eventName); - foreach (var subscription in subscriptions) - { - if (subscription.IsDynamic) - { - var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; - if (handler == null) continue; - dynamic eventData = JObject.Parse(message); - - await Task.Yield(); - await handler.Handle(eventData); - } - else - { - var handler = scope.ResolveOptional(subscription.HandlerType); - if (handler == null) continue; - var eventType = _subsManager.GetEventTypeByName(eventName); - var integrationEvent = JsonConvert.DeserializeObject(message, eventType); - var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); - - await Task.Yield(); - await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); - } - } + if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue; + using dynamic eventData = JsonDocument.Parse(message); + await Task.Yield(); + await handler.Handle(eventData); + } + else + { + var handler = scope.ResolveOptional(subscription.HandlerType); + if (handler == null) continue; + var eventType = _subsManager.GetEventTypeByName(eventName); + var integrationEvent = JsonSerializer.Deserialize(message, eventType, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + + await Task.Yield(); + await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); } } - else - { - _logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName); - } + } + else + { + _logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName); } } } diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj index 6da6eda9d..b6b23483c 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj @@ -1,15 +1,14 @@  - net5.0 + net6.0 Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ - - + diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/GlobalUsings.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/GlobalUsings.cs new file mode 100644 index 000000000..6fa5f0bf4 --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/GlobalUsings.cs @@ -0,0 +1,17 @@ +global using Microsoft.Extensions.Logging; +global using Polly; +global using Polly.Retry; +global using RabbitMQ.Client; +global using RabbitMQ.Client.Events; +global using RabbitMQ.Client.Exceptions; +global using System; +global using System.IO; +global using System.Net.Sockets; +global using Autofac; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; +global using System.Text; +global using System.Threading.Tasks; +global using System.Text.Json; diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersistentConnection.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersistentConnection.cs index 5893791c5..9d51e82a8 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersistentConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/IRabbitMQPersistentConnection.cs @@ -1,15 +1,11 @@ -using RabbitMQ.Client; -using System; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ +public interface IRabbitMQPersistentConnection + : IDisposable { - public interface IRabbitMQPersistentConnection - : IDisposable - { - bool IsConnected { get; } + bool IsConnected { get; } - bool TryConnect(); + bool TryConnect(); - IModel CreateModel(); - } + IModel CreateModel(); } diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs index 0dff4154b..64ad3e3b3 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/DefaultServiceBusPersisterConnection.cs @@ -1,68 +1,55 @@ -using Microsoft.Azure.ServiceBus; -using System; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus +public class DefaultServiceBusPersisterConnection : IServiceBusPersisterConnection { - public class DefaultServiceBusPersisterConnection : IServiceBusPersisterConnection - { - private readonly ServiceBusConnectionStringBuilder _serviceBusConnectionStringBuilder; - private readonly string _subscriptionClientName; - private SubscriptionClient _subscriptionClient; - private ITopicClient _topicClient; + private readonly string _serviceBusConnectionString; + private ServiceBusClient _topicClient; + private ServiceBusAdministrationClient _subscriptionClient; - bool _disposed; + bool _disposed; - public DefaultServiceBusPersisterConnection(ServiceBusConnectionStringBuilder serviceBusConnectionStringBuilder, - string subscriptionClientName) - { - _serviceBusConnectionStringBuilder = serviceBusConnectionStringBuilder ?? - throw new ArgumentNullException(nameof(serviceBusConnectionStringBuilder)); - _subscriptionClientName = subscriptionClientName; - _subscriptionClient = new SubscriptionClient(_serviceBusConnectionStringBuilder, subscriptionClientName); - _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy.Default); - } + public DefaultServiceBusPersisterConnection(string serviceBusConnectionString) + { + _serviceBusConnectionString = serviceBusConnectionString; + _subscriptionClient = new ServiceBusAdministrationClient(_serviceBusConnectionString); + _topicClient = new ServiceBusClient(_serviceBusConnectionString); + } - public ITopicClient TopicClient + public ServiceBusClient TopicClient + { + get { - get + if (_topicClient.IsClosed) { - if (_topicClient.IsClosedOrClosing) - { - _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy.Default); - } - return _topicClient; + _topicClient = new ServiceBusClient(_serviceBusConnectionString); } + return _topicClient; } + } - public ISubscriptionClient SubscriptionClient + public ServiceBusAdministrationClient AdministrationClient + { + get { - get - { - if (_subscriptionClient.IsClosedOrClosing) - { - _subscriptionClient = new SubscriptionClient(_serviceBusConnectionStringBuilder, _subscriptionClientName); - } - return _subscriptionClient; - } + return _subscriptionClient; } + } - public ServiceBusConnectionStringBuilder ServiceBusConnectionStringBuilder => _serviceBusConnectionStringBuilder; - - public ITopicClient CreateModel() + public ServiceBusClient CreateModel() + { + if (_topicClient.IsClosed) { - if (_topicClient.IsClosedOrClosing) - { - _topicClient = new TopicClient(_serviceBusConnectionStringBuilder, RetryPolicy.Default); - } - - return _topicClient; + _topicClient = new ServiceBusClient(_serviceBusConnectionString); } - public void Dispose() - { - if (_disposed) return; + return _topicClient; + } - _disposed = true; - } + public void Dispose() + { + if (_disposed) return; + + _disposed = true; + _topicClient.DisposeAsync().GetAwaiter().GetResult(); } } diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs index 841c303f7..52c5f50e4 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.cs @@ -1,203 +1,199 @@ -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; + +public class EventBusServiceBus : IEventBus, IDisposable { - using Autofac; - using Microsoft.Azure.ServiceBus; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using Microsoft.Extensions.Logging; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using System; - using System.Text; - using System.Threading.Tasks; - - public class EventBusServiceBus : IEventBus + private readonly IServiceBusPersisterConnection _serviceBusPersisterConnection; + private readonly ILogger _logger; + private readonly IEventBusSubscriptionsManager _subsManager; + private readonly ILifetimeScope _autofac; + private readonly string _topicName = "eshop_event_bus"; + private readonly string _subscriptionName; + private ServiceBusSender _sender; + private ServiceBusProcessor _processor; + private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; + private const string INTEGRATION_EVENT_SUFFIX = "IntegrationEvent"; + + public EventBusServiceBus(IServiceBusPersisterConnection serviceBusPersisterConnection, + ILogger logger, IEventBusSubscriptionsManager subsManager, ILifetimeScope autofac, string subscriptionClientName) { - private readonly IServiceBusPersisterConnection _serviceBusPersisterConnection; - private readonly ILogger _logger; - private readonly IEventBusSubscriptionsManager _subsManager; - private readonly ILifetimeScope _autofac; - private readonly string AUTOFAC_SCOPE_NAME = "eshop_event_bus"; - private const string INTEGRATION_EVENT_SUFFIX = "IntegrationEvent"; - - public EventBusServiceBus(IServiceBusPersisterConnection serviceBusPersisterConnection, - ILogger logger, IEventBusSubscriptionsManager subsManager, ILifetimeScope autofac) - { - _serviceBusPersisterConnection = serviceBusPersisterConnection; - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); - _autofac = autofac; - - RemoveDefaultRule(); - RegisterSubscriptionClientMessageHandler(); - } - - public void Publish(IntegrationEvent @event) - { - var eventName = @event.GetType().Name.Replace(INTEGRATION_EVENT_SUFFIX, ""); - var jsonMessage = JsonConvert.SerializeObject(@event); - var body = Encoding.UTF8.GetBytes(jsonMessage); - - var message = new Message - { - MessageId = Guid.NewGuid().ToString(), - Body = body, - Label = eventName, - }; - - _serviceBusPersisterConnection.TopicClient.SendAsync(message) - .GetAwaiter() - .GetResult(); - } - - public void SubscribeDynamic(string eventName) - where TH : IDynamicIntegrationEventHandler - { - _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).Name); + _serviceBusPersisterConnection = serviceBusPersisterConnection; + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _subsManager = subsManager ?? new InMemoryEventBusSubscriptionsManager(); + _autofac = autofac; + _subscriptionName = subscriptionClientName; + _sender = _serviceBusPersisterConnection.TopicClient.CreateSender(_topicName); + ServiceBusProcessorOptions options = new ServiceBusProcessorOptions { MaxConcurrentCalls = 10, AutoCompleteMessages = false }; + _processor = _serviceBusPersisterConnection.TopicClient.CreateProcessor(_topicName, _subscriptionName, options); + + RemoveDefaultRule(); + RegisterSubscriptionClientMessageHandlerAsync().GetAwaiter().GetResult(); + } - _subsManager.AddDynamicSubscription(eventName); - } + public void Publish(IntegrationEvent @event) + { + var eventName = @event.GetType().Name.Replace(INTEGRATION_EVENT_SUFFIX, ""); + var jsonMessage = JsonSerializer.Serialize(@event, @event.GetType()); + var body = Encoding.UTF8.GetBytes(jsonMessage); - public void Subscribe() - where T : IntegrationEvent - where TH : IIntegrationEventHandler + var message = new ServiceBusMessage { - var eventName = typeof(T).Name.Replace(INTEGRATION_EVENT_SUFFIX, ""); + MessageId = Guid.NewGuid().ToString(), + Body = new BinaryData(body), + Subject = eventName, + }; + + _sender.SendMessageAsync(message) + .GetAwaiter() + .GetResult(); + } - var containsKey = _subsManager.HasSubscriptionsForEvent(); - if (!containsKey) - { - try - { - _serviceBusPersisterConnection.SubscriptionClient.AddRuleAsync(new RuleDescription - { - Filter = new CorrelationFilter { Label = eventName }, - Name = eventName - }).GetAwaiter().GetResult(); - } - catch (ServiceBusException) - { - _logger.LogWarning("The messaging entity {eventName} already exists.", eventName); - } - } + public void SubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler + { + _logger.LogInformation("Subscribing to dynamic event {EventName} with {EventHandler}", eventName, typeof(TH).Name); - _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).Name); + _subsManager.AddDynamicSubscription(eventName); + } - _subsManager.AddSubscription(); - } + public void Subscribe() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = typeof(T).Name.Replace(INTEGRATION_EVENT_SUFFIX, ""); - public void Unsubscribe() - where T : IntegrationEvent - where TH : IIntegrationEventHandler + var containsKey = _subsManager.HasSubscriptionsForEvent(); + if (!containsKey) { - var eventName = typeof(T).Name.Replace(INTEGRATION_EVENT_SUFFIX, ""); - try { - _serviceBusPersisterConnection - .SubscriptionClient - .RemoveRuleAsync(eventName) - .GetAwaiter() - .GetResult(); + _serviceBusPersisterConnection.AdministrationClient.CreateRuleAsync(_topicName, _subscriptionName, new CreateRuleOptions + { + Filter = new CorrelationRuleFilter() { Subject = eventName }, + Name = eventName + }).GetAwaiter().GetResult(); } - catch (MessagingEntityNotFoundException) + catch (ServiceBusException) { - _logger.LogWarning("The messaging entity {eventName} Could not be found.", eventName); + _logger.LogWarning("The messaging entity {eventName} already exists.", eventName); } + } - _logger.LogInformation("Unsubscribing from event {EventName}", eventName); + _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).Name); - _subsManager.RemoveSubscription(); - } + _subsManager.AddSubscription(); + } - public void UnsubscribeDynamic(string eventName) - where TH : IDynamicIntegrationEventHandler - { - _logger.LogInformation("Unsubscribing from dynamic event {EventName}", eventName); + public void Unsubscribe() + where T : IntegrationEvent + where TH : IIntegrationEventHandler + { + var eventName = typeof(T).Name.Replace(INTEGRATION_EVENT_SUFFIX, ""); - _subsManager.RemoveDynamicSubscription(eventName); + try + { + _serviceBusPersisterConnection + .AdministrationClient + .DeleteRuleAsync(_topicName, _subscriptionName, eventName) + .GetAwaiter() + .GetResult(); } - - public void Dispose() + catch (ServiceBusException ex) when (ex.Reason == ServiceBusFailureReason.MessagingEntityNotFound) { - _subsManager.Clear(); + _logger.LogWarning("The messaging entity {eventName} Could not be found.", eventName); } - private void RegisterSubscriptionClientMessageHandler() - { - _serviceBusPersisterConnection.SubscriptionClient.RegisterMessageHandler( - async (message, token) => + _logger.LogInformation("Unsubscribing from event {EventName}", eventName); + + _subsManager.RemoveSubscription(); + } + + public void UnsubscribeDynamic(string eventName) + where TH : IDynamicIntegrationEventHandler + { + _logger.LogInformation("Unsubscribing from dynamic event {EventName}", eventName); + + _subsManager.RemoveDynamicSubscription(eventName); + } + + private async Task RegisterSubscriptionClientMessageHandlerAsync() + { + _processor.ProcessMessageAsync += + async (args) => + { + var eventName = $"{args.Message.Subject}{INTEGRATION_EVENT_SUFFIX}"; + string messageData = args.Message.Body.ToString(); + + // Complete the message so that it is not received again. + if (await ProcessEvent(eventName, messageData)) { - var eventName = $"{message.Label}{INTEGRATION_EVENT_SUFFIX}"; - var messageData = Encoding.UTF8.GetString(message.Body); - - // Complete the message so that it is not received again. - if (await ProcessEvent(eventName, messageData)) - { - await _serviceBusPersisterConnection.SubscriptionClient.CompleteAsync(message.SystemProperties.LockToken); - } - }, - new MessageHandlerOptions(ExceptionReceivedHandler) { MaxConcurrentCalls = 10, AutoComplete = false }); - } + await args.CompleteMessageAsync(args.Message); + } + }; - private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs) - { - var ex = exceptionReceivedEventArgs.Exception; - var context = exceptionReceivedEventArgs.ExceptionReceivedContext; + _processor.ProcessErrorAsync += ErrorHandler; + await _processor.StartProcessingAsync(); + } - _logger.LogError(ex, "ERROR handling message: {ExceptionMessage} - Context: {@ExceptionContext}", ex.Message, context); + public void Dispose() + { + _subsManager.Clear(); + _processor.CloseAsync().GetAwaiter().GetResult(); + } - return Task.CompletedTask; - } + private Task ErrorHandler(ProcessErrorEventArgs args) + { + var ex = args.Exception; + var context = args.ErrorSource; + + _logger.LogError(ex, "ERROR handling message: {ExceptionMessage} - Context: {@ExceptionContext}", ex.Message, context); - private async Task ProcessEvent(string eventName, string message) + return Task.CompletedTask; + } + + private async Task ProcessEvent(string eventName, string message) + { + var processed = false; + if (_subsManager.HasSubscriptionsForEvent(eventName)) { - var processed = false; - if (_subsManager.HasSubscriptionsForEvent(eventName)) + var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME); + var subscriptions = _subsManager.GetHandlersForEvent(eventName); + foreach (var subscription in subscriptions) { - using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) + if (subscription.IsDynamic) { - var subscriptions = _subsManager.GetHandlersForEvent(eventName); - foreach (var subscription in subscriptions) - { - if (subscription.IsDynamic) - { - var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler; - if (handler == null) continue; - dynamic eventData = JObject.Parse(message); - await handler.Handle(eventData); - } - else - { - var handler = scope.ResolveOptional(subscription.HandlerType); - if (handler == null) continue; - var eventType = _subsManager.GetEventTypeByName(eventName); - var integrationEvent = JsonConvert.DeserializeObject(message, eventType); - var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); - await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); - } - } + if (scope.ResolveOptional(subscription.HandlerType) is not IDynamicIntegrationEventHandler handler) continue; + + using dynamic eventData = JsonDocument.Parse(message); + await handler.Handle(eventData); + } + else + { + var handler = scope.ResolveOptional(subscription.HandlerType); + if (handler == null) continue; + var eventType = _subsManager.GetEventTypeByName(eventName); + var integrationEvent = JsonSerializer.Deserialize(message, eventType); + var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType); + await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent }); } - processed = true; } - return processed; } + processed = true; + return processed; + } - private void RemoveDefaultRule() + private void RemoveDefaultRule() + { + try { - try - { - _serviceBusPersisterConnection - .SubscriptionClient - .RemoveRuleAsync(RuleDescription.DefaultRuleName) - .GetAwaiter() - .GetResult(); - } - catch (MessagingEntityNotFoundException) - { - _logger.LogWarning("The messaging entity {DefaultRuleName} Could not be found.", RuleDescription.DefaultRuleName); - } + _serviceBusPersisterConnection + .AdministrationClient + .DeleteRuleAsync(_topicName, _subscriptionName, RuleProperties.DefaultRuleName) + .GetAwaiter() + .GetResult(); + } + catch (ServiceBusException ex) when (ex.Reason == ServiceBusFailureReason.MessagingEntityNotFound) + { + _logger.LogWarning("The messaging entity {DefaultRuleName} Could not be found.", RuleProperties.DefaultRuleName); } } -} +} \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj index 7bf222a59..e725de1c7 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj @@ -1,13 +1,13 @@  - net5.0 + net6.0 Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus - + diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/GlobalUsings.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/GlobalUsings.cs new file mode 100644 index 000000000..b0465794f --- /dev/null +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/GlobalUsings.cs @@ -0,0 +1,23 @@ +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using static Microsoft.eShopOnContainers.BuildingBlocks.EventBus.InMemoryEventBusSubscriptionsManager; +global using System.Collections.Generic; +global using System.Linq; +global using System.Text.Json.Serialization; +global using System.Threading.Tasks; +global using System; +global using Autofac; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.Extensions.Logging; +global using System.Text; +global using System.Text.Json; +global using Azure.Messaging.ServiceBus; +global using Azure.Messaging.ServiceBus.Administration; +global using System; + + + + + + + diff --git a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs index 8863db62e..834e00870 100644 --- a/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs +++ b/src/BuildingBlocks/EventBus/EventBusServiceBus/IServiceBusPersisterConnection.cs @@ -1,11 +1,7 @@ -namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus -{ - using Microsoft.Azure.ServiceBus; - using System; +namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; - public interface IServiceBusPersisterConnection : IDisposable - { - ITopicClient TopicClient { get; } - ISubscriptionClient SubscriptionClient { get; } - } +public interface IServiceBusPersisterConnection : IDisposable +{ + ServiceBusClient TopicClient { get; } + ServiceBusAdministrationClient AdministrationClient { get; } } \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs index 731ba17e8..caf305bab 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/EventStateEnum.cs @@ -1,10 +1,10 @@ -namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF +namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +public enum EventStateEnum { - public enum EventStateEnum - { - NotPublished = 0, - InProgress = 1, - Published = 2, - PublishedFailed = 3 - } + NotPublished = 0, + InProgress = 1, + Published = 2, + PublishedFailed = 3 } + diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/GlobalUsings.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/GlobalUsings.cs new file mode 100644 index 000000000..866b0cea6 --- /dev/null +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/GlobalUsings.cs @@ -0,0 +1,12 @@ +global using Microsoft.EntityFrameworkCore; +global using Microsoft.EntityFrameworkCore.Metadata.Builders; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using System; +global using System.Text.Json; +global using System.ComponentModel.DataAnnotations.Schema; +global using System.Linq; +global using System.Threading.Tasks; +global using Microsoft.EntityFrameworkCore.Storage; +global using System.Collections.Generic; +global using System.Data.Common; +global using System.Reflection; diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs index b51705538..1b59a4191 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogContext.cs @@ -1,45 +1,41 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; +namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF +public class IntegrationEventLogContext : DbContext { - public class IntegrationEventLogContext : DbContext + public IntegrationEventLogContext(DbContextOptions options) : base(options) { - public IntegrationEventLogContext(DbContextOptions options) : base(options) - { - } + } - public DbSet IntegrationEventLogs { get; set; } + public DbSet IntegrationEventLogs { get; set; } - protected override void OnModelCreating(ModelBuilder builder) - { - builder.Entity(ConfigureIntegrationEventLogEntry); - } + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity(ConfigureIntegrationEventLogEntry); + } - void ConfigureIntegrationEventLogEntry(EntityTypeBuilder builder) - { - builder.ToTable("IntegrationEventLog"); + void ConfigureIntegrationEventLogEntry(EntityTypeBuilder builder) + { + builder.ToTable("IntegrationEventLog"); - builder.HasKey(e => e.EventId); + builder.HasKey(e => e.EventId); - builder.Property(e => e.EventId) - .IsRequired(); + builder.Property(e => e.EventId) + .IsRequired(); - builder.Property(e => e.Content) - .IsRequired(); + builder.Property(e => e.Content) + .IsRequired(); - builder.Property(e => e.CreationTime) - .IsRequired(); + builder.Property(e => e.CreationTime) + .IsRequired(); - builder.Property(e => e.State) - .IsRequired(); + builder.Property(e => e.State) + .IsRequired(); - builder.Property(e => e.TimesSent) - .IsRequired(); + builder.Property(e => e.TimesSent) + .IsRequired(); - builder.Property(e => e.EventTypeName) - .IsRequired(); + builder.Property(e => e.EventTypeName) + .IsRequired(); - } } } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj index c9ed73500..c68db458e 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj @@ -1,19 +1,18 @@  - net5.0 + net6.0 Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs index 977dd0547..90826f22e 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs @@ -1,40 +1,36 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Newtonsoft.Json; -using System; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; +namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF +public class IntegrationEventLogEntry { - public class IntegrationEventLogEntry + private IntegrationEventLogEntry() { } + public IntegrationEventLogEntry(IntegrationEvent @event, Guid transactionId) { - private IntegrationEventLogEntry() { } - public IntegrationEventLogEntry(IntegrationEvent @event, Guid transactionId) + EventId = @event.Id; + CreationTime = @event.CreationDate; + EventTypeName = @event.GetType().FullName; + Content = JsonSerializer.Serialize(@event, @event.GetType(), new JsonSerializerOptions { - EventId = @event.Id; - CreationTime = @event.CreationDate; - EventTypeName = @event.GetType().FullName; - Content = JsonConvert.SerializeObject(@event); - State = EventStateEnum.NotPublished; - TimesSent = 0; - TransactionId = transactionId.ToString(); - } - public Guid EventId { get; private set; } - public string EventTypeName { get; private set; } - [NotMapped] - public string EventTypeShortName => EventTypeName.Split('.')?.Last(); - [NotMapped] - public IntegrationEvent IntegrationEvent { get; private set; } - public EventStateEnum State { get; set; } - public int TimesSent { get; set; } - public DateTime CreationTime { get; private set; } - public string Content { get; private set; } - public string TransactionId { get; private set; } + WriteIndented = true + }); + State = EventStateEnum.NotPublished; + TimesSent = 0; + TransactionId = transactionId.ToString(); + } + public Guid EventId { get; private set; } + public string EventTypeName { get; private set; } + [NotMapped] + public string EventTypeShortName => EventTypeName.Split('.')?.Last(); + [NotMapped] + public IntegrationEvent IntegrationEvent { get; private set; } + public EventStateEnum State { get; set; } + public int TimesSent { get; set; } + public DateTime CreationTime { get; private set; } + public string Content { get; private set; } + public string TransactionId { get; private set; } - public IntegrationEventLogEntry DeserializeJsonContent(Type type) - { - IntegrationEvent = JsonConvert.DeserializeObject(Content, type) as IntegrationEvent; - return this; - } + public IntegrationEventLogEntry DeserializeJsonContent(Type type) + { + IntegrationEvent = JsonSerializer.Deserialize(Content, type, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }) as IntegrationEvent; + return this; } } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs index 93fd11143..44e03b414 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs @@ -1,17 +1,10 @@ -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; -namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services +public interface IIntegrationEventLogService { - public interface IIntegrationEventLogService - { - Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId); - Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction); - Task MarkEventAsPublishedAsync(Guid eventId); - Task MarkEventAsInProgressAsync(Guid eventId); - Task MarkEventAsFailedAsync(Guid eventId); - } + Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId); + Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction); + Task MarkEventAsPublishedAsync(Guid eventId); + Task MarkEventAsInProgressAsync(Guid eventId); + Task MarkEventAsFailedAsync(Guid eventId); } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs index 12957479b..472fba6e9 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs @@ -1,110 +1,99 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services -{ - public class IntegrationEventLogService : IIntegrationEventLogService, IDisposable - { - private readonly IntegrationEventLogContext _integrationEventLogContext; - private readonly DbConnection _dbConnection; - private readonly List _eventTypes; - private volatile bool disposedValue; +namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; - public IntegrationEventLogService(DbConnection dbConnection) - { - _dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection)); - _integrationEventLogContext = new IntegrationEventLogContext( - new DbContextOptionsBuilder() - .UseSqlServer(_dbConnection) - .Options); - - _eventTypes = Assembly.Load(Assembly.GetEntryAssembly().FullName) - .GetTypes() - .Where(t => t.Name.EndsWith(nameof(IntegrationEvent))) - .ToList(); - } +public class IntegrationEventLogService : IIntegrationEventLogService, IDisposable +{ + private readonly IntegrationEventLogContext _integrationEventLogContext; + private readonly DbConnection _dbConnection; + private readonly List _eventTypes; + private volatile bool _disposedValue; - public async Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId) - { - var tid = transactionId.ToString(); + public IntegrationEventLogService(DbConnection dbConnection) + { + _dbConnection = dbConnection ?? throw new ArgumentNullException(nameof(dbConnection)); + _integrationEventLogContext = new IntegrationEventLogContext( + new DbContextOptionsBuilder() + .UseSqlServer(_dbConnection) + .Options); + + _eventTypes = Assembly.Load(Assembly.GetEntryAssembly().FullName) + .GetTypes() + .Where(t => t.Name.EndsWith(nameof(IntegrationEvent))) + .ToList(); + } - var result = await _integrationEventLogContext.IntegrationEventLogs - .Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished).ToListAsync(); + public async Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId) + { + var tid = transactionId.ToString(); - if (result != null && result.Any()) - { - return result.OrderBy(o => o.CreationTime) - .Select(e => e.DeserializeJsonContent(_eventTypes.Find(t => t.Name == e.EventTypeShortName))); - } + var result = await _integrationEventLogContext.IntegrationEventLogs + .Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished).ToListAsync(); - return new List(); + if (result != null && result.Any()) + { + return result.OrderBy(o => o.CreationTime) + .Select(e => e.DeserializeJsonContent(_eventTypes.Find(t => t.Name == e.EventTypeShortName))); } - public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction) - { - if (transaction == null) throw new ArgumentNullException(nameof(transaction)); + return new List(); + } - var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId); + public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction) + { + if (transaction == null) throw new ArgumentNullException(nameof(transaction)); - _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction()); - _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry); + var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId); - return _integrationEventLogContext.SaveChangesAsync(); - } + _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction()); + _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry); - public Task MarkEventAsPublishedAsync(Guid eventId) - { - return UpdateEventStatus(eventId, EventStateEnum.Published); - } + return _integrationEventLogContext.SaveChangesAsync(); + } - public Task MarkEventAsInProgressAsync(Guid eventId) - { - return UpdateEventStatus(eventId, EventStateEnum.InProgress); - } + public Task MarkEventAsPublishedAsync(Guid eventId) + { + return UpdateEventStatus(eventId, EventStateEnum.Published); + } - public Task MarkEventAsFailedAsync(Guid eventId) - { - return UpdateEventStatus(eventId, EventStateEnum.PublishedFailed); - } + public Task MarkEventAsInProgressAsync(Guid eventId) + { + return UpdateEventStatus(eventId, EventStateEnum.InProgress); + } - private Task UpdateEventStatus(Guid eventId, EventStateEnum status) - { - var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == eventId); - eventLogEntry.State = status; + public Task MarkEventAsFailedAsync(Guid eventId) + { + return UpdateEventStatus(eventId, EventStateEnum.PublishedFailed); + } + + private Task UpdateEventStatus(Guid eventId, EventStateEnum status) + { + var eventLogEntry = _integrationEventLogContext.IntegrationEventLogs.Single(ie => ie.EventId == eventId); + eventLogEntry.State = status; - if (status == EventStateEnum.InProgress) - eventLogEntry.TimesSent++; + if (status == EventStateEnum.InProgress) + eventLogEntry.TimesSent++; - _integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry); + _integrationEventLogContext.IntegrationEventLogs.Update(eventLogEntry); - return _integrationEventLogContext.SaveChangesAsync(); - } + return _integrationEventLogContext.SaveChangesAsync(); + } - protected virtual void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) { - if (!disposedValue) + if (disposing) { - if (disposing) - { - _integrationEventLogContext?.Dispose(); - } + _integrationEventLogContext?.Dispose(); + } - disposedValue = true; - } + _disposedValue = true; } + } - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); - } + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); } } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs index 8dbb070d3..5ba8093b2 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Utilities/ResilientTransaction.cs @@ -1,31 +1,23 @@ -using Microsoft.EntityFrameworkCore; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities; -namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities +public class ResilientTransaction { - public class ResilientTransaction - { - private DbContext _context; - private ResilientTransaction(DbContext context) => - _context = context ?? throw new ArgumentNullException(nameof(context)); + private DbContext _context; + private ResilientTransaction(DbContext context) => + _context = context ?? throw new ArgumentNullException(nameof(context)); - public static ResilientTransaction New(DbContext context) => - new ResilientTransaction(context); + public static ResilientTransaction New(DbContext context) => new(context); - public async Task ExecuteAsync(Func action) + public async Task ExecuteAsync(Func action) + { + //Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction(): + //See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + var strategy = _context.Database.CreateExecutionStrategy(); + await strategy.ExecuteAsync(async () => { - //Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction(): - //See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - var strategy = _context.Database.CreateExecutionStrategy(); - await strategy.ExecuteAsync(async () => - { - using (var transaction = _context.Database.BeginTransaction()) - { - await action(); - transaction.Commit(); - } - }); - } + using var transaction = _context.Database.BeginTransaction(); + await action(); + transaction.Commit(); + }); } } diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj index 19aaa282f..5c094de1e 100644 --- a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj +++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false diff --git a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs index 6316ae59d..3c7fc105a 100644 --- a/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs +++ b/src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs @@ -21,48 +21,46 @@ namespace Microsoft.AspNetCore.Hosting { var underK8s = webHost.IsInKubernetes(); - using (var scope = webHost.Services.CreateScope()) + using var scope = webHost.Services.CreateScope(); + var services = scope.ServiceProvider; + var logger = services.GetRequiredService>(); + var context = services.GetService(); + + try { - var services = scope.ServiceProvider; - var logger = services.GetRequiredService>(); - var context = services.GetService(); + logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - try + if (underK8s) { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retries = 10; - var retry = Policy.Handle() - .WaitAndRetry( - retryCount: retries, - sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } + InvokeSeeder(seeder, context, services); + } + else + { + var retries = 10; + var retry = Policy.Handle() + .WaitAndRetry( + retryCount: retries, + sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), + onRetry: (exception, timeSpan, retry, ctx) => + { + logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); + }); - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + //if the sql server container is not created on run docker compose this + //migration can't fail for network related exception. The retry options for DbContext only + //apply to transient exceptions + // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + retry.Execute(() => InvokeSeeder(seeder, context, services)); } - catch (Exception ex) + + logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + if (underK8s) { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } + throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } diff --git a/src/Services/Basket/Basket.API/Auth/Server/AuthorizationHeaderParameterOperationFilter.cs b/src/Services/Basket/Basket.API/Auth/Server/AuthorizationHeaderParameterOperationFilter.cs index 3d505b4ee..2acda7be8 100644 --- a/src/Services/Basket/Basket.API/Auth/Server/AuthorizationHeaderParameterOperationFilter.cs +++ b/src/Services/Basket/Basket.API/Auth/Server/AuthorizationHeaderParameterOperationFilter.cs @@ -1,33 +1,25 @@ -using Microsoft.AspNetCore.Mvc.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server +public class AuthorizationHeaderParameterOperationFilter : IOperationFilter { - public class AuthorizationHeaderParameterOperationFilter : IOperationFilter + public void Apply(OpenApiOperation operation, OperationFilterContext context) { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors; - var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter); - var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter); + var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors; + var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter); + var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter); - if (isAuthorized && !allowAnonymous) - { - if (operation.Parameters == null) - operation.Parameters = new List(); + if (isAuthorized && !allowAnonymous) + { + operation.Parameters ??= new List(); - operation.Parameters.Add(new OpenApiParameter - { - Name = "Authorization", - In = ParameterLocation.Header, - Description = "access token", - Required = true - }); - } + operation.Parameters.Add(new OpenApiParameter + { + Name = "Authorization", + In = ParameterLocation.Header, + Description = "access token", + Required = true + }); } } } diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index 741407c10..ebb224824 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -1,12 +1,10 @@  - - net5.0 + net6.0 $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; ..\..\..\..\docker-compose.dcproj false - true - preview + true @@ -15,31 +13,37 @@ - - + + + + - + - - - - - - - - + + + + + + + + + + - - - - - - - - + + + + + + + + + - + + @@ -53,5 +57,4 @@ - diff --git a/src/Services/Basket/Basket.API/BasketSettings.cs b/src/Services/Basket/Basket.API/BasketSettings.cs index 064d615ec..9db883101 100644 --- a/src/Services/Basket/Basket.API/BasketSettings.cs +++ b/src/Services/Basket/Basket.API/BasketSettings.cs @@ -1,7 +1,7 @@ -namespace Microsoft.eShopOnContainers.Services.Basket.API +namespace Microsoft.eShopOnContainers.Services.Basket.API; + +public class BasketSettings { - public class BasketSettings - { - public string ConnectionString { get; set; } - } + public string ConnectionString { get; set; } } + diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs index 0a3b5879b..5468bbc15 100644 --- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs +++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs @@ -1,103 +1,89 @@ -using Basket.API.IntegrationEvents.Events; -using Basket.API.Model; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.eShopOnContainers.Services.Basket.API.Services; -using Microsoft.Extensions.Logging; -using System; -using System.Net; -using System.Security.Claims; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers +[Route("api/v1/[controller]")] +[Authorize] +[ApiController] +public class BasketController : ControllerBase { - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class BasketController : ControllerBase - { - private readonly IBasketRepository _repository; - private readonly IIdentityService _identityService; - private readonly IEventBus _eventBus; - private readonly ILogger _logger; - - public BasketController( - ILogger logger, - IBasketRepository repository, - IIdentityService identityService, - IEventBus eventBus) - { - _logger = logger; - _repository = repository; - _identityService = identityService; - _eventBus = eventBus; - } + private readonly IBasketRepository _repository; + private readonly IIdentityService _identityService; + private readonly IEventBus _eventBus; + private readonly ILogger _logger; - [HttpGet("{id}")] - [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] - public async Task> GetBasketByIdAsync(string id) - { - var basket = await _repository.GetBasketAsync(id); - - return Ok(basket ?? new CustomerBasket(id)); - } + public BasketController( + ILogger logger, + IBasketRepository repository, + IIdentityService identityService, + IEventBus eventBus) + { + _logger = logger; + _repository = repository; + _identityService = identityService; + _eventBus = eventBus; + } - [HttpPost] - [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] - public async Task> UpdateBasketAsync([FromBody] CustomerBasket value) - { - return Ok(await _repository.UpdateBasketAsync(value)); - } + [HttpGet("{id}")] + [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] + public async Task> GetBasketByIdAsync(string id) + { + var basket = await _repository.GetBasketAsync(id); - [Route("checkout")] - [HttpPost] - [ProducesResponseType((int)HttpStatusCode.Accepted)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - public async Task CheckoutAsync([FromBody] BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId) - { - var userId = _identityService.GetUserIdentity(); + return Ok(basket ?? new CustomerBasket(id)); + } - basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ? - guid : basketCheckout.RequestId; + [HttpPost] + [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] + public async Task> UpdateBasketAsync([FromBody] CustomerBasket value) + { + return Ok(await _repository.UpdateBasketAsync(value)); + } - var basket = await _repository.GetBasketAsync(userId); + [Route("checkout")] + [HttpPost] + [ProducesResponseType((int)HttpStatusCode.Accepted)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + public async Task CheckoutAsync([FromBody] BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId) + { + var userId = _identityService.GetUserIdentity(); - if (basket == null) - { - return BadRequest(); - } + basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ? + guid : basketCheckout.RequestId; - var userName = this.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value; + var basket = await _repository.GetBasketAsync(userId); - var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street, - basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName, - basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket); + if (basket == null) + { + return BadRequest(); + } - // Once basket is checkout, sends an integration event to - // ordering.api to convert basket to order and proceeds with - // order creation process - try - { - _eventBus.Publish(eventMessage); - } - catch (Exception ex) - { - _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, Program.AppName); + var userName = this.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value; - throw; - } + var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street, + basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName, + basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket); - return Accepted(); + // Once basket is checkout, sends an integration event to + // ordering.api to convert basket to order and proceeds with + // order creation process + try + { + _eventBus.Publish(eventMessage); } - - // DELETE api/values/5 - [HttpDelete("{id}")] - [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] - public async Task DeleteBasketByIdAsync(string id) + catch (Exception ex) { - await _repository.DeleteBasketAsync(id); + _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, Program.AppName); + + throw; } + + return Accepted(); + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] + public async Task DeleteBasketByIdAsync(string id) + { + await _repository.DeleteBasketAsync(id); } } diff --git a/src/Services/Basket/Basket.API/Controllers/HomeController.cs b/src/Services/Basket/Basket.API/Controllers/HomeController.cs index d0c37a205..8b2b7c2e7 100644 --- a/src/Services/Basket/Basket.API/Controllers/HomeController.cs +++ b/src/Services/Basket/Basket.API/Controllers/HomeController.cs @@ -1,13 +1,11 @@ -using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers +public class HomeController : Controller { - public class HomeController : Controller + // GET: // + public IActionResult Index() { - // GET: // - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } + return new RedirectResult("~/swagger"); } } + diff --git a/src/Services/Basket/Basket.API/Dockerfile b/src/Services/Basket/Basket.API/Dockerfile index de2718ad4..9cd4abba8 100644 --- a/src/Services/Basket/Basket.API/Dockerfile +++ b/src/Services/Basket/Basket.API/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Basket/Basket.API/Dockerfile.develop b/src/Services/Basket/Basket.API/Dockerfile.develop index 4ad633175..8f8312673 100644 --- a/src/Services/Basket/Basket.API/Dockerfile.develop +++ b/src/Services/Basket/Basket.API/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Basket/Basket.API/GlobalUsings.cs b/src/Services/Basket/Basket.API/GlobalUsings.cs new file mode 100644 index 000000000..75f7a878e --- /dev/null +++ b/src/Services/Basket/Basket.API/GlobalUsings.cs @@ -0,0 +1,61 @@ +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using Azure.Core; +global using Azure.Identity; +global using Basket.API.Infrastructure.ActionResults; +global using Basket.API.Infrastructure.Exceptions; +global using Basket.API.Infrastructure.Filters; +global using Basket.API.Infrastructure.Middlewares; +global using Basket.API.IntegrationEvents.EventHandling; +global using Basket.API.IntegrationEvents.Events; +global using Basket.API.Model; +global using Grpc.Core; +global using GrpcBasket; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http.Features; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc.Authorization; +global using Microsoft.AspNetCore.Mvc.Filters; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore.Server.Kestrel.Core; +global using Microsoft.AspNetCore; +global using Azure.Messaging.ServiceBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +global using Microsoft.eShopOnContainers.Services.Basket.API.Controllers; +global using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; +global using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling; +global using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; +global using Microsoft.eShopOnContainers.Services.Basket.API.Model; +global using Microsoft.eShopOnContainers.Services.Basket.API.Services; +global using Microsoft.eShopOnContainers.Services.Basket.API; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Microsoft.OpenApi.Models; +global using RabbitMQ.Client; +global using Serilog.Context; +global using Serilog; +global using StackExchange.Redis; +global using Swashbuckle.AspNetCore.SwaggerGen; +global using System.Collections.Generic; +global using System.ComponentModel.DataAnnotations; +global using System.IdentityModel.Tokens.Jwt; +global using System.IO; +global using System.Linq; +global using System.Net; +global using System.Security.Claims; +global using System.Text.Json; +global using System.Threading.Tasks; +global using System; \ No newline at end of file diff --git a/src/Services/Basket/Basket.API/Grpc/BasketService.cs b/src/Services/Basket/Basket.API/Grpc/BasketService.cs index 51633b326..50c23c0ff 100644 --- a/src/Services/Basket/Basket.API/Grpc/BasketService.cs +++ b/src/Services/Basket/Basket.API/Grpc/BasketService.cs @@ -1,102 +1,94 @@ -using Grpc.Core; -using Microsoft.AspNetCore.Authorization; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; - -namespace GrpcBasket +namespace GrpcBasket; + +public class BasketService : Basket.BasketBase { - public class BasketService : Basket.BasketBase + private readonly IBasketRepository _repository; + private readonly ILogger _logger; + + public BasketService(IBasketRepository repository, ILogger logger) + { + _repository = repository; + _logger = logger; + } + + [AllowAnonymous] + public override async Task GetBasketById(BasketRequest request, ServerCallContext context) { - private readonly IBasketRepository _repository; - private readonly ILogger _logger; + _logger.LogInformation("Begin grpc call from method {Method} for basket id {Id}", context.Method, request.Id); + + var data = await _repository.GetBasketAsync(request.Id); - public BasketService(IBasketRepository repository, ILogger logger) + if (data != null) { - _repository = repository; - _logger = logger; - } + context.Status = new Status(StatusCode.OK, $"Basket with id {request.Id} do exist"); - [AllowAnonymous] - public override async Task GetBasketById(BasketRequest request, ServerCallContext context) + return MapToCustomerBasketResponse(data); + } + else { - _logger.LogInformation("Begin grpc call from method {Method} for basket id {Id}", context.Method, request.Id); + context.Status = new Status(StatusCode.NotFound, $"Basket with id {request.Id} do not exist"); + } - var data = await _repository.GetBasketAsync(request.Id); + return new CustomerBasketResponse(); + } - if (data != null) - { - context.Status = new Status(StatusCode.OK, $"Basket with id {request.Id} do exist"); + public override async Task UpdateBasket(CustomerBasketRequest request, ServerCallContext context) + { + _logger.LogInformation("Begin grpc call BasketService.UpdateBasketAsync for buyer id {Buyerid}", request.Buyerid); - return MapToCustomerBasketResponse(data); - } - else - { - context.Status = new Status(StatusCode.NotFound, $"Basket with id {request.Id} do not exist"); - } + var customerBasket = MapToCustomerBasket(request); - return new CustomerBasketResponse(); - } + var response = await _repository.UpdateBasketAsync(customerBasket); - public override async Task UpdateBasket(CustomerBasketRequest request, ServerCallContext context) + if (response != null) { - _logger.LogInformation("Begin grpc call BasketService.UpdateBasketAsync for buyer id {Buyerid}", request.Buyerid); - - var customerBasket = MapToCustomerBasket(request); + return MapToCustomerBasketResponse(response); + } - var response = await _repository.UpdateBasketAsync(customerBasket); + context.Status = new Status(StatusCode.NotFound, $"Basket with buyer id {request.Buyerid} do not exist"); - if (response != null) - { - return MapToCustomerBasketResponse(response); - } + return null; + } - context.Status = new Status(StatusCode.NotFound, $"Basket with buyer id {request.Buyerid} do not exist"); + private CustomerBasketResponse MapToCustomerBasketResponse(CustomerBasket customerBasket) + { + var response = new CustomerBasketResponse + { + Buyerid = customerBasket.BuyerId + }; - return null; - } + customerBasket.Items.ForEach(item => response.Items.Add(new BasketItemResponse + { + Id = item.Id, + Oldunitprice = (double)item.OldUnitPrice, + Pictureurl = item.PictureUrl, + Productid = item.ProductId, + Productname = item.ProductName, + Quantity = item.Quantity, + Unitprice = (double)item.UnitPrice + })); + + return response; + } - private CustomerBasketResponse MapToCustomerBasketResponse(CustomerBasket customerBasket) + private CustomerBasket MapToCustomerBasket(CustomerBasketRequest customerBasketRequest) + { + var response = new CustomerBasket { - var response = new CustomerBasketResponse - { - Buyerid = customerBasket.BuyerId - }; - - customerBasket.Items.ForEach(item => response.Items.Add(new BasketItemResponse - { - Id = item.Id, - Oldunitprice = (double)item.OldUnitPrice, - Pictureurl = item.PictureUrl, - Productid = item.ProductId, - Productname = item.ProductName, - Quantity = item.Quantity, - Unitprice = (double)item.UnitPrice - })); - - return response; - } + BuyerId = customerBasketRequest.Buyerid + }; - private CustomerBasket MapToCustomerBasket(CustomerBasketRequest customerBasketRequest) + customerBasketRequest.Items.ToList().ForEach(item => response.Items.Add(new BasketItem { - var response = new CustomerBasket - { - BuyerId = customerBasketRequest.Buyerid - }; - - customerBasketRequest.Items.ToList().ForEach(item => response.Items.Add(new BasketItem - { - Id = item.Id, - OldUnitPrice = (decimal)item.Oldunitprice, - PictureUrl = item.Pictureurl, - ProductId = item.Productid, - ProductName = item.Productname, - Quantity = item.Quantity, - UnitPrice = (decimal)item.Unitprice - })); - - return response; - } + Id = item.Id, + OldUnitPrice = (decimal)item.Oldunitprice, + PictureUrl = item.Pictureurl, + ProductId = item.Productid, + ProductName = item.Productname, + Quantity = item.Quantity, + UnitPrice = (decimal)item.Unitprice + })); + + return response; } } diff --git a/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs index a0b988156..5f95e586e 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs @@ -1,14 +1,11 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +namespace Basket.API.Infrastructure.ActionResults; -namespace Basket.API.Infrastructure.ActionResults +public class InternalServerErrorObjectResult : ObjectResult { - public class InternalServerErrorObjectResult : ObjectResult + public InternalServerErrorObjectResult(object error) + : base(error) { - public InternalServerErrorObjectResult(object error) - : base(error) - { - StatusCode = StatusCodes.Status500InternalServerError; - } + StatusCode = StatusCodes.Status500InternalServerError; } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Exceptions/BasketDomainException.cs b/src/Services/Basket/Basket.API/Infrastructure/Exceptions/BasketDomainException.cs index e0f2df6fa..0502b7924 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Exceptions/BasketDomainException.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Exceptions/BasketDomainException.cs @@ -1,21 +1,16 @@ -using System; +namespace Basket.API.Infrastructure.Exceptions; -namespace Basket.API.Infrastructure.Exceptions +public class BasketDomainException : Exception { - /// - /// Exception type for app exceptions - /// - public class BasketDomainException : Exception - { - public BasketDomainException() - { } + public BasketDomainException() + { } - public BasketDomainException(string message) - : base(message) - { } + public BasketDomainException(string message) + : base(message) + { } - public BasketDomainException(string message, Exception innerException) - : base(message, innerException) - { } - } + public BasketDomainException(string message, Exception innerException) + : base(message, innerException) + { } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Exceptions/FailingMiddlewareAppBuilderExtensions.cs b/src/Services/Basket/Basket.API/Infrastructure/Exceptions/FailingMiddlewareAppBuilderExtensions.cs index a09f32f76..66f55dddd 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Exceptions/FailingMiddlewareAppBuilderExtensions.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Exceptions/FailingMiddlewareAppBuilderExtensions.cs @@ -1,20 +1,18 @@ -using Microsoft.AspNetCore.Builder; -using System; +namespace Basket.API.Infrastructure.Middlewares; -namespace Basket.API.Infrastructure.Middlewares +public static class FailingMiddlewareAppBuilderExtensions { - public static class FailingMiddlewareAppBuilderExtensions + public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder) { - public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder) - { - return UseFailingMiddleware(builder, null); - } - public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder, Action action) - { - var options = new FailingOptions(); - action?.Invoke(options); - builder.UseMiddleware(options); - return builder; - } + return UseFailingMiddleware(builder, null); + } + + public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder, Action action) + { + var options = new FailingOptions(); + action?.Invoke(options); + builder.UseMiddleware(options); + return builder; } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Basket/Basket.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs index 0fd08a0a9..00b0b5195 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs @@ -1,58 +1,47 @@ -using Basket.API.Infrastructure.ActionResults; -using Basket.API.Infrastructure.Exceptions; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System.Net; +namespace Basket.API.Infrastructure.Filters; - -namespace Basket.API.Infrastructure.Filters +public partial class HttpGlobalExceptionFilter : IExceptionFilter { - public partial class HttpGlobalExceptionFilter : IExceptionFilter + private readonly IWebHostEnvironment env; + private readonly ILogger logger; + + public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) { - private readonly IWebHostEnvironment env; - private readonly ILogger logger; + this.env = env; + this.logger = logger; + } - public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) - { - this.env = env; - this.logger = logger; - } + public void OnException(ExceptionContext context) + { + logger.LogError(new EventId(context.Exception.HResult), + context.Exception, + context.Exception.Message); - public void OnException(ExceptionContext context) + if (context.Exception.GetType() == typeof(BasketDomainException)) { - logger.LogError(new EventId(context.Exception.HResult), - context.Exception, - context.Exception.Message); - - if (context.Exception.GetType() == typeof(BasketDomainException)) + var json = new JsonErrorResponse { - var json = new JsonErrorResponse - { - Messages = new[] { context.Exception.Message } - }; + Messages = new[] { context.Exception.Message } + }; - context.Result = new BadRequestObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - else + context.Result = new BadRequestObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + } + else + { + var json = new JsonErrorResponse { - var json = new JsonErrorResponse - { - Messages = new[] { "An error occurred. Try it again." } - }; + Messages = new[] { "An error occurred. Try it again." } + }; - if (env.IsDevelopment()) - { - json.DeveloperMessage = context.Exception; - } - - context.Result = new InternalServerErrorObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + if (env.IsDevelopment()) + { + json.DeveloperMessage = context.Exception; } - context.ExceptionHandled = true; + + context.Result = new InternalServerErrorObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } + context.ExceptionHandled = true; } } diff --git a/src/Services/Basket/Basket.API/Infrastructure/Filters/JsonErrorResponse.cs b/src/Services/Basket/Basket.API/Infrastructure/Filters/JsonErrorResponse.cs index bcadc7358..88bc02eda 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Filters/JsonErrorResponse.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Filters/JsonErrorResponse.cs @@ -1,9 +1,9 @@ -namespace Basket.API.Infrastructure.Filters +namespace Basket.API.Infrastructure.Filters; + +public class JsonErrorResponse { - public class JsonErrorResponse - { - public string[] Messages { get; set; } + public string[] Messages { get; set; } - public object DeveloperMessage { get; set; } - } + public object DeveloperMessage { get; set; } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Filters/ValidateModelStateFilter.cs b/src/Services/Basket/Basket.API/Infrastructure/Filters/ValidateModelStateFilter.cs index 3e4c3e072..5c97b85dc 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Filters/ValidateModelStateFilter.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Filters/ValidateModelStateFilter.cs @@ -1,30 +1,26 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using System.Linq; +namespace Basket.API.Infrastructure.Filters; -namespace Basket.API.Infrastructure.Filters +public class ValidateModelStateFilter : ActionFilterAttribute { - public class ValidateModelStateFilter : ActionFilterAttribute + public override void OnActionExecuting(ActionExecutingContext context) { - public override void OnActionExecuting(ActionExecutingContext context) + if (context.ModelState.IsValid) { - if (context.ModelState.IsValid) - { - return; - } + return; + } - var validationErrors = context.ModelState - .Keys - .SelectMany(k => context.ModelState[k].Errors) - .Select(e => e.ErrorMessage) - .ToArray(); + var validationErrors = context.ModelState + .Keys + .SelectMany(k => context.ModelState[k].Errors) + .Select(e => e.ErrorMessage) + .ToArray(); - var json = new JsonErrorResponse - { - Messages = validationErrors - }; + var json = new JsonErrorResponse + { + Messages = validationErrors + }; - context.Result = new BadRequestObjectResult(json); - } + context.Result = new BadRequestObjectResult(json); } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs index 4a1c24aa6..9608ec0a7 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/AuthorizeCheckOperationFilter.cs @@ -1,36 +1,29 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; +namespace Basket.API.Infrastructure.Filters; -namespace Basket.API.Infrastructure.Filters +public class AuthorizeCheckOperationFilter : IOperationFilter { - public class AuthorizeCheckOperationFilter : IOperationFilter + public void Apply(OpenApiOperation operation, OperationFilterContext context) { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - // Check for authorize attribute - var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || - context.MethodInfo.GetCustomAttributes(true).OfType().Any(); + // Check for authorize attribute + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - if (!hasAuthorize) return; + if (!hasAuthorize) return; - operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); - operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); + operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); - var oAuthScheme = new OpenApiSecurityScheme - { - Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } - }; + var oAuthScheme = new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } + }; - operation.Security = new List + operation.Security = new List + { + new() { - new OpenApiSecurityRequirement - { - [ oAuthScheme ] = new [] { "basketapi" } - } - }; - } + [ oAuthScheme ] = new [] { "basketapi" } + } + }; } -} \ No newline at end of file +} diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingMiddleware.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingMiddleware.cs index 0019a2049..60fbdb655 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingMiddleware.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingMiddleware.cs @@ -1,95 +1,90 @@ -using Microsoft.AspNetCore.Http; +namespace Basket.API.Infrastructure.Middlewares; + using Microsoft.Extensions.Logging; -using System; -using System.Linq; -using System.Threading.Tasks; -namespace Basket.API.Infrastructure.Middlewares +public class FailingMiddleware { - public class FailingMiddleware + private readonly RequestDelegate _next; + private bool _mustFail; + private readonly FailingOptions _options; + private readonly ILogger _logger; + + public FailingMiddleware(RequestDelegate next, ILogger logger, FailingOptions options) { - private readonly RequestDelegate _next; - private bool _mustFail; - private readonly FailingOptions _options; - private readonly ILogger _logger; + _next = next; + _options = options; + _mustFail = false; + _logger = logger; + } - public FailingMiddleware(RequestDelegate next, ILogger logger, FailingOptions options) + public async Task Invoke(HttpContext context) + { + var path = context.Request.Path; + if (path.Equals(_options.ConfigPath, StringComparison.OrdinalIgnoreCase)) { - _next = next; - _options = options; - _mustFail = false; - _logger = logger; + await ProcessConfigRequest(context); + return; } - public async Task Invoke(HttpContext context) + if (MustFail(context)) { - var path = context.Request.Path; - if (path.Equals(_options.ConfigPath, StringComparison.OrdinalIgnoreCase)) - { - await ProcessConfigRequest(context); - return; - } - - if (MustFail(context)) - { - _logger.LogInformation("Response for path {Path} will fail.", path); - context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; - context.Response.ContentType = "text/plain"; - await context.Response.WriteAsync("Failed due to FailingMiddleware enabled."); - } - else - { - await _next.Invoke(context); - } + _logger.LogInformation("Response for path {Path} will fail.", path); + context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; + context.Response.ContentType = "text/plain"; + await context.Response.WriteAsync("Failed due to FailingMiddleware enabled."); } - - private async Task ProcessConfigRequest(HttpContext context) + else { - var enable = context.Request.Query.Keys.Any(k => k == "enable"); - var disable = context.Request.Query.Keys.Any(k => k == "disable"); + await _next.Invoke(context); + } + } - if (enable && disable) - { - throw new ArgumentException("Must use enable or disable querystring values, but not both"); - } + private async Task ProcessConfigRequest(HttpContext context) + { + var enable = context.Request.Query.Keys.Any(k => k == "enable"); + var disable = context.Request.Query.Keys.Any(k => k == "disable"); - if (disable) - { - _mustFail = false; - await SendOkResponse(context, "FailingMiddleware disabled. Further requests will be processed."); - return; - } - if (enable) - { - _mustFail = true; - await SendOkResponse(context, "FailingMiddleware enabled. Further requests will return HTTP 500"); - return; - } + if (enable && disable) + { + throw new ArgumentException("Must use enable or disable querystring values, but not both"); + } - // If reach here, that means that no valid parameter has been passed. Just output status - await SendOkResponse(context, string.Format("FailingMiddleware is {0}", _mustFail ? "enabled" : "disabled")); + if (disable) + { + _mustFail = false; + await SendOkResponse(context, "FailingMiddleware disabled. Further requests will be processed."); return; } - - private async Task SendOkResponse(HttpContext context, string message) + if (enable) { - context.Response.StatusCode = (int)System.Net.HttpStatusCode.OK; - context.Response.ContentType = "text/plain"; - await context.Response.WriteAsync(message); + _mustFail = true; + await SendOkResponse(context, "FailingMiddleware enabled. Further requests will return HTTP 500"); + return; } - private bool MustFail(HttpContext context) - { - var rpath = context.Request.Path.Value; + // If reach here, that means that no valid parameter has been passed. Just output status + await SendOkResponse(context, string.Format("FailingMiddleware is {0}", _mustFail ? "enabled" : "disabled")); + return; + } - if (_options.NotFilteredPaths.Any(p => p.Equals(rpath, StringComparison.InvariantCultureIgnoreCase))) - { - return false; - } + private async Task SendOkResponse(HttpContext context, string message) + { + context.Response.StatusCode = (int)System.Net.HttpStatusCode.OK; + context.Response.ContentType = "text/plain"; + await context.Response.WriteAsync(message); + } + + private bool MustFail(HttpContext context) + { + var rpath = context.Request.Path.Value; - return _mustFail && - (_options.EndpointPaths.Any(x => x == rpath) - || _options.EndpointPaths.Count == 0); + if (_options.NotFilteredPaths.Any(p => p.Equals(rpath, StringComparison.InvariantCultureIgnoreCase))) + { + return false; } + + return _mustFail && + (_options.EndpointPaths.Any(x => x == rpath) + || _options.EndpointPaths.Count == 0); } } diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingOptions.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingOptions.cs index e8a77f1fd..7818938d2 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingOptions.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingOptions.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; +namespace Basket.API.Infrastructure.Middlewares; -namespace Basket.API.Infrastructure.Middlewares +public class FailingOptions { - public class FailingOptions - { - public string ConfigPath = "/Failing"; - public List EndpointPaths { get; set; } = new List(); + public string ConfigPath = "/Failing"; + public List EndpointPaths { get; set; } = new List(); - public List NotFilteredPaths { get; set; } = new List(); - } + public List NotFilteredPaths { get; set; } = new List(); } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingStartupFilter.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingStartupFilter.cs index 7d3b2ce18..74da62b5d 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingStartupFilter.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingStartupFilter.cs @@ -1,24 +1,20 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using System; +namespace Basket.API.Infrastructure.Middlewares; -namespace Basket.API.Infrastructure.Middlewares +public class FailingStartupFilter : IStartupFilter { - public class FailingStartupFilter : IStartupFilter + private readonly Action _options; + public FailingStartupFilter(Action optionsAction) { - private readonly Action _options; - public FailingStartupFilter(Action optionsAction) - { - _options = optionsAction; - } + _options = optionsAction; + } - public Action Configure(Action next) + public Action Configure(Action next) + { + return app => { - return app => - { - app.UseFailingMiddleware(_options); - next(app); - }; - } + app.UseFailingMiddleware(_options); + next(app); + }; } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingWebHostBuilderExtensions.cs b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingWebHostBuilderExtensions.cs index 99be1b182..8a8ba9523 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingWebHostBuilderExtensions.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Middlewares/FailingWebHostBuilderExtensions.cs @@ -1,18 +1,14 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using System; +namespace Basket.API.Infrastructure.Middlewares; -namespace Basket.API.Infrastructure.Middlewares +public static class WebHostBuildertExtensions { - public static class WebHostBuildertExtensions + public static IWebHostBuilder UseFailing(this IWebHostBuilder builder, Action options) { - public static IWebHostBuilder UseFailing(this IWebHostBuilder builder, Action options) + builder.ConfigureServices(services => { - builder.ConfigureServices(services => - { - services.AddSingleton(new FailingStartupFilter(options)); - }); - return builder; - } + services.AddSingleton(new FailingStartupFilter(options)); + }); + return builder; } } + diff --git a/src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs b/src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs index 93adcc023..7db463f20 100644 --- a/src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Infrastructure/Repositories/RedisBasketRepository.cs @@ -1,70 +1,64 @@ -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using StackExchange.Redis; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories +public class RedisBasketRepository : IBasketRepository { - public class RedisBasketRepository : IBasketRepository + private readonly ILogger _logger; + private readonly ConnectionMultiplexer _redis; + private readonly IDatabase _database; + + public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis) { - private readonly ILogger _logger; - private readonly ConnectionMultiplexer _redis; - private readonly IDatabase _database; + _logger = loggerFactory.CreateLogger(); + _redis = redis; + _database = redis.GetDatabase(); + } - public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis) - { - _logger = loggerFactory.CreateLogger(); - _redis = redis; - _database = redis.GetDatabase(); - } + public async Task DeleteBasketAsync(string id) + { + return await _database.KeyDeleteAsync(id); + } - public async Task DeleteBasketAsync(string id) - { - return await _database.KeyDeleteAsync(id); - } + public IEnumerable GetUsers() + { + var server = GetServer(); + var data = server.Keys(); - public IEnumerable GetUsers() - { - var server = GetServer(); - var data = server.Keys(); + return data?.Select(k => k.ToString()); + } - return data?.Select(k => k.ToString()); - } + public async Task GetBasketAsync(string customerId) + { + var data = await _database.StringGetAsync(customerId); - public async Task GetBasketAsync(string customerId) + if (data.IsNullOrEmpty) { - var data = await _database.StringGetAsync(customerId); - - if (data.IsNullOrEmpty) - { - return null; - } - - return JsonConvert.DeserializeObject(data); + return null; } - public async Task UpdateBasketAsync(CustomerBasket basket) + return JsonSerializer.Deserialize(data, new JsonSerializerOptions { - var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket)); - - if (!created) - { - _logger.LogInformation("Problem occur persisting the item."); - return null; - } - - _logger.LogInformation("Basket item persisted succesfully."); + PropertyNameCaseInsensitive = true + }); + } - return await GetBasketAsync(basket.BuyerId); - } + public async Task UpdateBasketAsync(CustomerBasket basket) + { + var created = await _database.StringSetAsync(basket.BuyerId, JsonSerializer.Serialize(basket)); - private IServer GetServer() + if (!created) { - var endpoint = _redis.GetEndPoints(); - return _redis.GetServer(endpoint.First()); + _logger.LogInformation("Problem occur persisting the item."); + return null; } + + _logger.LogInformation("Basket item persisted succesfully."); + + return await GetBasketAsync(basket.BuyerId); + } + + private IServer GetServer() + { + var endpoint = _redis.GetEndPoints(); + return _redis.GetServer(endpoint.First()); } } diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs index fb2c10e9e..2c93f82fd 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/OrderStartedIntegrationEventHandler.cs @@ -1,37 +1,29 @@ -using Basket.API.IntegrationEvents.Events; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.Extensions.Logging; -using Serilog.Context; -using System; -using System.Threading.Tasks; - -namespace Basket.API.IntegrationEvents.EventHandling +namespace Basket.API.IntegrationEvents.EventHandling; + +public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IBasketRepository _repository; - private readonly ILogger _logger; + private readonly IBasketRepository _repository; + private readonly ILogger _logger; - public OrderStartedIntegrationEventHandler( - IBasketRepository repository, - ILogger logger) - { - _repository = repository ?? throw new ArgumentNullException(nameof(repository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStartedIntegrationEventHandler( + IBasketRepository repository, + ILogger logger) + { + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStartedIntegrationEvent @event) + public async Task Handle(OrderStartedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _repository.DeleteBasketAsync(@event.UserId.ToString()); - } + await _repository.DeleteBasketAsync(@event.UserId.ToString()); } } } + diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs index 6068bdda6..b389b73d7 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/EventHandling/ProductPriceChangedIntegrationEventHandler.cs @@ -1,64 +1,53 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.Extensions.Logging; -using Serilog.Context; -using System; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling; -namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling +public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler { - public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler - { - private readonly ILogger _logger; - private readonly IBasketRepository _repository; + private readonly ILogger _logger; + private readonly IBasketRepository _repository; - public ProductPriceChangedIntegrationEventHandler( - ILogger logger, - IBasketRepository repository) - { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _repository = repository ?? throw new ArgumentNullException(nameof(repository)); - } + public ProductPriceChangedIntegrationEventHandler( + ILogger logger, + IBasketRepository repository) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); + } - public async Task Handle(ProductPriceChangedIntegrationEvent @event) + public async Task Handle(ProductPriceChangedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var userIds = _repository.GetUsers(); + var userIds = _repository.GetUsers(); - foreach (var id in userIds) - { - var basket = await _repository.GetBasketAsync(id); + foreach (var id in userIds) + { + var basket = await _repository.GetBasketAsync(id); - await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket); - } + await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket); } } + } - private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, decimal oldPrice, CustomerBasket basket) + private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, decimal oldPrice, CustomerBasket basket) + { + var itemsToUpdate = basket?.Items?.Where(x => x.ProductId == productId).ToList(); + + if (itemsToUpdate != null) { - var itemsToUpdate = basket?.Items?.Where(x => x.ProductId == productId).ToList(); + _logger.LogInformation("----- ProductPriceChangedIntegrationEventHandler - Updating items in basket for user: {BuyerId} ({@Items})", basket.BuyerId, itemsToUpdate); - if (itemsToUpdate != null) + foreach (var item in itemsToUpdate) { - _logger.LogInformation("----- ProductPriceChangedIntegrationEventHandler - Updating items in basket for user: {BuyerId} ({@Items})", basket.BuyerId, itemsToUpdate); - - foreach (var item in itemsToUpdate) + if (item.UnitPrice == oldPrice) { - if (item.UnitPrice == oldPrice) - { - var originalPrice = item.UnitPrice; - item.UnitPrice = newPrice; - item.OldUnitPrice = originalPrice; - } + var originalPrice = item.UnitPrice; + item.UnitPrice = newPrice; + item.OldUnitPrice = originalPrice; } - await _repository.UpdateBasketAsync(basket); } + await _repository.UpdateBasketAsync(basket); } } } - diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs b/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs index e0567b54e..f6f3b0380 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs @@ -1,15 +1,12 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Basket.API.IntegrationEvents.Events; -namespace Basket.API.IntegrationEvents.Events +// Integration Events notes: +// An Event is "something that has happened in the past", therefore its name has to be +// An Integration Event is an event that can cause side effects to other microservices, Bounded-Contexts or external systems. +public record OrderStartedIntegrationEvent : IntegrationEvent { - // Integration Events notes: - // An Event is “something that has happened in the past”, therefore its name has to be - // An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems. - public record OrderStartedIntegrationEvent : IntegrationEvent - { - public string UserId { get; init; } + public string UserId { get; init; } - public OrderStartedIntegrationEvent(string userId) - => UserId = userId; - } + public OrderStartedIntegrationEvent(string userId) + => UserId = userId; } diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs b/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs index c69fe0f72..9db9fe90b 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs @@ -1,23 +1,20 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; -namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events +// Integration Events notes: +// An Event is "something that has happened in the past", therefore its name has to be +// An Integration Event is an event that can cause side effects to other microservices, Bounded-Contexts or external systems. +public record ProductPriceChangedIntegrationEvent : IntegrationEvent { - // Integration Events notes: - // An Event is “something that has happened in the past”, therefore its name has to be - // An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems. - public record ProductPriceChangedIntegrationEvent : IntegrationEvent - { - public int ProductId { get; private init; } + public int ProductId { get; private init; } - public decimal NewPrice { get; private init; } + public decimal NewPrice { get; private init; } - public decimal OldPrice { get; private init; } + public decimal OldPrice { get; private init; } - public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice) - { - ProductId = productId; - NewPrice = newPrice; - OldPrice = oldPrice; - } + public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice) + { + ProductId = productId; + NewPrice = newPrice; + OldPrice = oldPrice; } } diff --git a/src/Services/Basket/Basket.API/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs b/src/Services/Basket/Basket.API/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs index e79e0fbdd..d57a32c25 100644 --- a/src/Services/Basket/Basket.API/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs +++ b/src/Services/Basket/Basket.API/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs @@ -1,64 +1,59 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using System; +namespace Basket.API.IntegrationEvents.Events; -namespace Basket.API.IntegrationEvents.Events +public record UserCheckoutAcceptedIntegrationEvent : IntegrationEvent { - public record UserCheckoutAcceptedIntegrationEvent : IntegrationEvent - { - public string UserId { get; } - - public string UserName { get; } + public string UserId { get; } - public int OrderNumber { get; init; } + public string UserName { get; } - public string City { get; init; } + public int OrderNumber { get; init; } - public string Street { get; init; } + public string City { get; init; } - public string State { get; init; } + public string Street { get; init; } - public string Country { get; init; } + public string State { get; init; } - public string ZipCode { get; init; } + public string Country { get; init; } - public string CardNumber { get; init; } + public string ZipCode { get; init; } - public string CardHolderName { get; init; } + public string CardNumber { get; init; } - public DateTime CardExpiration { get; init; } + public string CardHolderName { get; init; } - public string CardSecurityNumber { get; init; } + public DateTime CardExpiration { get; init; } - public int CardTypeId { get; init; } + public string CardSecurityNumber { get; init; } - public string Buyer { get; init; } + public int CardTypeId { get; init; } - public Guid RequestId { get; init; } + public string Buyer { get; init; } - public CustomerBasket Basket { get; } + public Guid RequestId { get; init; } - public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street, - string state, string country, string zipCode, string cardNumber, string cardHolderName, - DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, - CustomerBasket basket) - { - UserId = userId; - UserName = userName; - City = city; - Street = street; - State = state; - Country = country; - ZipCode = zipCode; - CardNumber = cardNumber; - CardHolderName = cardHolderName; - CardExpiration = cardExpiration; - CardSecurityNumber = cardSecurityNumber; - CardTypeId = cardTypeId; - Buyer = buyer; - Basket = basket; - RequestId = requestId; - } + public CustomerBasket Basket { get; } + public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street, + string state, string country, string zipCode, string cardNumber, string cardHolderName, + DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, + CustomerBasket basket) + { + UserId = userId; + UserName = userName; + City = city; + Street = street; + State = state; + Country = country; + ZipCode = zipCode; + CardNumber = cardNumber; + CardHolderName = cardHolderName; + CardExpiration = cardExpiration; + CardSecurityNumber = cardSecurityNumber; + CardTypeId = cardTypeId; + Buyer = buyer; + Basket = basket; + RequestId = requestId; } + } diff --git a/src/Services/Basket/Basket.API/Model/BasketCheckout.cs b/src/Services/Basket/Basket.API/Model/BasketCheckout.cs index 410700773..5340444d7 100644 --- a/src/Services/Basket/Basket.API/Model/BasketCheckout.cs +++ b/src/Services/Basket/Basket.API/Model/BasketCheckout.cs @@ -1,32 +1,28 @@ -using System; +namespace Basket.API.Model; -namespace Basket.API.Model +public class BasketCheckout { - public class BasketCheckout - { - public string City { get; set; } + public string City { get; set; } - public string Street { get; set; } + public string Street { get; set; } - public string State { get; set; } + public string State { get; set; } - public string Country { get; set; } + public string Country { get; set; } - public string ZipCode { get; set; } + public string ZipCode { get; set; } - public string CardNumber { get; set; } + public string CardNumber { get; set; } - public string CardHolderName { get; set; } + public string CardHolderName { get; set; } - public DateTime CardExpiration { get; set; } + public DateTime CardExpiration { get; set; } - public string CardSecurityNumber { get; set; } + public string CardSecurityNumber { get; set; } - public int CardTypeId { get; set; } + public int CardTypeId { get; set; } - public string Buyer { get; set; } + public string Buyer { get; set; } - public Guid RequestId { get; set; } - } + public Guid RequestId { get; set; } } - diff --git a/src/Services/Basket/Basket.API/Model/BasketItem.cs b/src/Services/Basket/Basket.API/Model/BasketItem.cs index f781d5a60..85ebdb9a4 100644 --- a/src/Services/Basket/Basket.API/Model/BasketItem.cs +++ b/src/Services/Basket/Basket.API/Model/BasketItem.cs @@ -1,27 +1,24 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Model; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Model +public class BasketItem : IValidatableObject { - public class BasketItem : IValidatableObject - { - public string Id { get; set; } - public int ProductId { get; set; } - public string ProductName { get; set; } - public decimal UnitPrice { get; set; } - public decimal OldUnitPrice { get; set; } - public int Quantity { get; set; } - public string PictureUrl { get; set; } - public IEnumerable Validate(ValidationContext validationContext) - { - var results = new List(); + public string Id { get; set; } + public int ProductId { get; set; } + public string ProductName { get; set; } + public decimal UnitPrice { get; set; } + public decimal OldUnitPrice { get; set; } + public int Quantity { get; set; } + public string PictureUrl { get; set; } - if (Quantity < 1) - { - results.Add(new ValidationResult("Invalid number of units", new[] { "Quantity" })); - } + public IEnumerable Validate(ValidationContext validationContext) + { + var results = new List(); - return results; + if (Quantity < 1) + { + results.Add(new ValidationResult("Invalid number of units", new[] { "Quantity" })); } + + return results; } } diff --git a/src/Services/Basket/Basket.API/Model/CustomerBasket.cs b/src/Services/Basket/Basket.API/Model/CustomerBasket.cs index 9ae495d4f..2ca370be8 100644 --- a/src/Services/Basket/Basket.API/Model/CustomerBasket.cs +++ b/src/Services/Basket/Basket.API/Model/CustomerBasket.cs @@ -1,21 +1,19 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Model; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Model +public class CustomerBasket { - public class CustomerBasket - { - public string BuyerId { get; set; } + public string BuyerId { get; set; } - public List Items { get; set; } = new List(); + public List Items { get; set; } = new(); - public CustomerBasket() - { + public CustomerBasket() + { - } + } - public CustomerBasket(string customerId) - { - BuyerId = customerId; - } + public CustomerBasket(string customerId) + { + BuyerId = customerId; } } + diff --git a/src/Services/Basket/Basket.API/Model/IBasketRepository.cs b/src/Services/Basket/Basket.API/Model/IBasketRepository.cs index 850b5b637..6081919fa 100644 --- a/src/Services/Basket/Basket.API/Model/IBasketRepository.cs +++ b/src/Services/Basket/Basket.API/Model/IBasketRepository.cs @@ -1,13 +1,10 @@ -using System.Collections.Generic; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Model; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Model +public interface IBasketRepository { - public interface IBasketRepository - { - Task GetBasketAsync(string customerId); - IEnumerable GetUsers(); - Task UpdateBasketAsync(CustomerBasket basket); - Task DeleteBasketAsync(string id); - } + Task GetBasketAsync(string customerId); + IEnumerable GetUsers(); + Task UpdateBasketAsync(CustomerBasket basket); + Task DeleteBasketAsync(string id); } + diff --git a/src/Services/Basket/Basket.API/Program.cs b/src/Services/Basket/Basket.API/Program.cs index 058735a07..fd57afc82 100644 --- a/src/Services/Basket/Basket.API/Program.cs +++ b/src/Services/Basket/Basket.API/Program.cs @@ -1,16 +1,4 @@ -using Basket.API.Infrastructure.Middlewares; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.eShopOnContainers.Services.Basket.API; -using Microsoft.Extensions.Configuration; -using Serilog; -using System; -using System.IO; -using System.Net; - -var configuration = GetConfiguration(); +var configuration = GetConfiguration(); Log.Logger = CreateSerilogLogger(configuration); @@ -62,7 +50,7 @@ IWebHost BuildWebHost(IConfiguration configuration, string[] args) => .UseSerilog() .Build(); -ILogger CreateSerilogLogger(IConfiguration configuration) +Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { var seqServerUrl = configuration["Serilog:SeqServerUrl"]; var logstashUrl = configuration["Serilog:LogstashgUrl"]; @@ -88,10 +76,11 @@ IConfiguration GetConfiguration() if (config.GetValue("UseVault", false)) { - builder.AddAzureKeyVault( - $"https://{config["Vault:Name"]}.vault.azure.net/", + TokenCredential credential = new ClientSecretCredential( + config["Vault:TenantId"], config["Vault:ClientId"], config["Vault:ClientSecret"]); + builder.AddAzureKeyVault(new Uri($"https://{config["Vault:Name"]}.vault.azure.net/"), credential); } return builder.Build(); @@ -104,9 +93,9 @@ IConfiguration GetConfiguration() return (port, grpcPort); } -public class Program +public partial class Program { public static string Namespace = typeof(Startup).Namespace; public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); -} \ No newline at end of file +} diff --git a/src/Services/Basket/Basket.API/Services/IIdentityService.cs b/src/Services/Basket/Basket.API/Services/IIdentityService.cs index fe84e23d5..2e4d395e9 100644 --- a/src/Services/Basket/Basket.API/Services/IIdentityService.cs +++ b/src/Services/Basket/Basket.API/Services/IIdentityService.cs @@ -1,7 +1,7 @@ -namespace Microsoft.eShopOnContainers.Services.Basket.API.Services +namespace Microsoft.eShopOnContainers.Services.Basket.API.Services; + +public interface IIdentityService { - public interface IIdentityService - { - string GetUserIdentity(); - } + string GetUserIdentity(); } + diff --git a/src/Services/Basket/Basket.API/Services/IdentityService.cs b/src/Services/Basket/Basket.API/Services/IdentityService.cs index bc6b2faf4..9dded4ea3 100644 --- a/src/Services/Basket/Basket.API/Services/IdentityService.cs +++ b/src/Services/Basket/Basket.API/Services/IdentityService.cs @@ -1,21 +1,17 @@ - -using Microsoft.AspNetCore.Http; -using System; +namespace Microsoft.eShopOnContainers.Services.Basket.API.Services; -namespace Microsoft.eShopOnContainers.Services.Basket.API.Services +public class IdentityService : IIdentityService { - public class IdentityService : IIdentityService - { - private IHttpContextAccessor _context; + private IHttpContextAccessor _context; - public IdentityService(IHttpContextAccessor context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + public IdentityService(IHttpContextAccessor context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } - public string GetUserIdentity() - { - return _context.HttpContext.User.FindFirst("sub").Value; - } + public string GetUserIdentity() + { + return _context.HttpContext.User.FindFirst("sub").Value; } } + diff --git a/src/Services/Basket/Basket.API/Startup.cs b/src/Services/Basket/Basket.API/Startup.cs index 2f53cbcb0..082560048 100644 --- a/src/Services/Basket/Basket.API/Startup.cs +++ b/src/Services/Basket/Basket.API/Startup.cs @@ -1,363 +1,321 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using Basket.API.Infrastructure.Filters; -using Basket.API.IntegrationEvents.EventHandling; -using Basket.API.IntegrationEvents.Events; -using GrpcBasket; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Azure.ServiceBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -using Microsoft.eShopOnContainers.Services.Basket.API.Controllers; -using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; -using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling; -using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.eShopOnContainers.Services.Basket.API.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; -using RabbitMQ.Client; -using StackExchange.Redis; -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; -using System.IO; - -namespace Microsoft.eShopOnContainers.Services.Basket.API +namespace Microsoft.eShopOnContainers.Services.Basket.API; +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. - public virtual IServiceProvider ConfigureServices(IServiceCollection services) + // This method gets called by the runtime. Use this method to add services to the container. + public virtual IServiceProvider ConfigureServices(IServiceCollection services) + { + services.AddGrpc(options => { - services.AddGrpc(options => - { - options.EnableDetailedErrors = true; - }); + options.EnableDetailedErrors = true; + }); - RegisterAppInsights(services); + RegisterAppInsights(services); - services.AddControllers(options => - { - options.Filters.Add(typeof(HttpGlobalExceptionFilter)); - options.Filters.Add(typeof(ValidateModelStateFilter)); + services.AddControllers(options => + { + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + options.Filters.Add(typeof(ValidateModelStateFilter)); - }) // Added for functional tests - .AddApplicationPart(typeof(BasketController).Assembly) - .AddNewtonsoftJson(); + }) // Added for functional tests + .AddApplicationPart(typeof(BasketController).Assembly) + .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); - services.AddSwaggerGen(options => + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "eShopOnContainers - Basket HTTP API", - Version = "v1", - Description = "The Basket Service HTTP API" - }); + Title = "eShopOnContainers - Basket HTTP API", + Version = "v1", + Description = "The Basket Service HTTP API" + }); - options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() + Implicit = new OpenApiOAuthFlow() { - Implicit = new OpenApiOAuthFlow() + AuthorizationUrl = new Uri($"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), + TokenUrl = new Uri($"{Configuration.GetValue("IdentityUrlExternal")}/connect/token"), + Scopes = new Dictionary() { - AuthorizationUrl = new Uri($"{Configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), - TokenUrl = new Uri($"{Configuration.GetValue("IdentityUrlExternal")}/connect/token"), - Scopes = new Dictionary() - { - { "basket", "Basket API" } - } + { "basket", "Basket API" } } } - }); - - options.OperationFilter(); + } }); - ConfigureAuthService(services); + options.OperationFilter(); + }); - services.AddCustomHealthCheck(Configuration); + ConfigureAuthService(services); - services.Configure(Configuration); + services.AddCustomHealthCheck(Configuration); - //By connecting here we are making sure that our service - //cannot start until redis is ready. This might slow down startup, - //but given that there is a delay on resolving the ip address - //and then creating the connection it seems reasonable to move - //that cost to startup instead of having the first request pay the - //penalty. - services.AddSingleton(sp => - { - var settings = sp.GetRequiredService>().Value; - var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); + services.Configure(Configuration); - configuration.ResolveDns = true; + //By connecting here we are making sure that our service + //cannot start until redis is ready. This might slow down startup, + //but given that there is a delay on resolving the ip address + //and then creating the connection it seems reasonable to move + //that cost to startup instead of having the first request pay the + //penalty. + services.AddSingleton(sp => + { + var settings = sp.GetRequiredService>().Value; + var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); - return ConnectionMultiplexer.Connect(configuration); - }); + return ConnectionMultiplexer.Connect(configuration); + }); - if (Configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var serviceBusConnectionString = Configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - - var subscriptionClientName = Configuration["SubscriptionClientName"]; - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); - }); - } - else + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); + var serviceBusConnectionString = Configuration["EventBusConnection"]; - var factory = new ConnectionFactory() - { - HostName = Configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; - - if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) - { - factory.UserName = Configuration["EventBusUserName"]; - } - - if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) - { - factory.Password = Configuration["EventBusPassword"]; - } + return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); + }); + } + else + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"], + DispatchConsumersAsync = true + }; - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } + if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) + { + factory.UserName = Configuration["EventBusUserName"]; + } - RegisterEventBus(services); + if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) + { + factory.Password = Configuration["EventBusPassword"]; + } + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .SetIsOriginAllowed((host) => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); - services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); + } - services.AddOptions(); + RegisterEventBus(services); - var container = new ContainerBuilder(); - container.Populate(services); - return new AutofacServiceProvider(container.Build()); - } + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + + services.AddOptions(); + + var container = new ContainerBuilder(); + container.Populate(services); + + return new AutofacServiceProvider(container.Build()); + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + //loggerFactory.AddAzureWebAppDiagnostics(); + //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) { - //loggerFactory.AddAzureWebAppDiagnostics(); - //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + app.UsePathBase(pathBase); + } - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) + app.UseSwagger() + .UseSwaggerUI(setup => { - app.UsePathBase(pathBase); - } - - app.UseSwagger() - .UseSwaggerUI(setup => - { - setup.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1"); - setup.OAuthClientId("basketswaggerui"); - setup.OAuthAppName("Basket Swagger UI"); - }); + setup.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1"); + setup.OAuthClientId("basketswaggerui"); + setup.OAuthAppName("Basket Swagger UI"); + }); - app.UseRouting(); - app.UseCors("CorsPolicy"); - ConfigureAuth(app); + app.UseRouting(); + app.UseCors("CorsPolicy"); + ConfigureAuth(app); - app.UseStaticFiles(); + app.UseStaticFiles(); - app.UseEndpoints(endpoints => + app.UseEndpoints(endpoints => + { + endpoints.MapGrpcService(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapGet("/_proto/", async ctx => { - endpoints.MapGrpcService(); - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapGet("/_proto/", async ctx => + ctx.Response.ContentType = "text/plain"; + using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read); + using var sr = new StreamReader(fs); + while (!sr.EndOfStream) { - ctx.Response.ContentType = "text/plain"; - using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read); - using var sr = new StreamReader(fs); - while (!sr.EndOfStream) + var line = await sr.ReadLineAsync(); + if (line != "/* >>" || line != "<< */") { - var line = await sr.ReadLineAsync(); - if (line != "/* >>" || line != "<< */") - { - await ctx.Response.WriteAsync(line); - } + await ctx.Response.WriteAsync(line); } - }); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); + } + }); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions + { + Predicate = r => r.Name.Contains("self") + }); + }); - ConfigureEventBus(app); - } + ConfigureEventBus(app); + } - private void RegisterAppInsights(IServiceCollection services) - { - services.AddApplicationInsightsTelemetry(Configuration); - services.AddApplicationInsightsKubernetesEnricher(); - } + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + services.AddApplicationInsightsKubernetesEnricher(); + } + + private void ConfigureAuthService(IServiceCollection services) + { + // prevent from mapping "sub" claim to nameidentifier. + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - private void ConfigureAuthService(IServiceCollection services) + var identityUrl = Configuration.GetValue("IdentityUrl"); + + services.AddAuthentication(options => { - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - var identityUrl = Configuration.GetValue("IdentityUrl"); + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "basket"; + }); + } - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + protected virtual void ConfigureAuth(IApplicationBuilder app) + { + app.UseAuthentication(); + app.UseAuthorization(); + } - }).AddJwtBearer(options => + private void RegisterEventBus(IServiceCollection services) + { + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "basket"; + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); }); } - - protected virtual void ConfigureAuth(IApplicationBuilder app) - { - app.UseAuthentication(); - app.UseAuthorization(); - } - - private void RegisterEventBus(IServiceCollection services) + else { - if (Configuration.GetValue("AzureServiceBusEnabled")) + services.AddSingleton(sp => { - services.AddSingleton(sp => + var subscriptionClientName = Configuration["SubscriptionClientName"]; + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, iLifetimeScope); - }); - } - else - { - services.AddSingleton(sp => - { - var subscriptionClientName = Configuration["SubscriptionClientName"]; - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } - services.AddSingleton(); + services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); - } + services.AddTransient(); + services.AddTransient(); + } - private void ConfigureEventBus(IApplicationBuilder app) - { - var eventBus = app.ApplicationServices.GetRequiredService(); + private void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe(); - eventBus.Subscribe(); - } + eventBus.Subscribe(); + eventBus.Subscribe(); } +} - public static class CustomExtensionMethods +public static class CustomExtensionMethods +{ + public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var hcBuilder = services.AddHealthChecks(); + var hcBuilder = services.AddHealthChecks(); - hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); + hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); - hcBuilder - .AddRedis( - configuration["ConnectionString"], - name: "redis-check", - tags: new string[] { "redis" }); + hcBuilder + .AddRedis( + configuration["ConnectionString"], + name: "redis-check", + tags: new string[] { "redis" }); - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "basket-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "basket-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } - - return services; + if (configuration.GetValue("AzureServiceBusEnabled")) + { + hcBuilder + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "basket-servicebus-check", + tags: new string[] { "servicebus" }); + } + else + { + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "basket-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); } + + return services; } -} +} \ No newline at end of file diff --git a/src/Services/Basket/Basket.API/TestHttpResponseTrailersFeature.cs b/src/Services/Basket/Basket.API/TestHttpResponseTrailersFeature.cs index 7cab5a07b..b1cfef87b 100644 --- a/src/Services/Basket/Basket.API/TestHttpResponseTrailersFeature.cs +++ b/src/Services/Basket/Basket.API/TestHttpResponseTrailersFeature.cs @@ -1,10 +1,6 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; +namespace Microsoft.eShopOnContainers.Services.Basket.API; -namespace Microsoft.eShopOnContainers.Services.Basket.API +internal class TestHttpResponseTrailersFeature : IHttpResponseTrailersFeature { - internal class TestHttpResponseTrailersFeature : IHttpResponseTrailersFeature - { - public IHeaderDictionary Trailers { get; set; } - } -} \ No newline at end of file + public IHeaderDictionary Trailers { get; set; } +} diff --git a/src/Services/Basket/Basket.API/appsettings.json b/src/Services/Basket/Basket.API/appsettings.json index a5b723116..295294308 100644 --- a/src/Services/Basket/Basket.API/appsettings.json +++ b/src/Services/Basket/Basket.API/appsettings.json @@ -24,7 +24,7 @@ "UseVault": false, "Vault": { "Name": "eshop", - "ClientId": "your-clien-id", + "ClientId": "your-client-id", "ClientSecret": "your-client-secret" } -} \ No newline at end of file +} diff --git a/src/Services/Basket/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs b/src/Services/Basket/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs index d83f81996..6343dbe68 100644 --- a/src/Services/Basket/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs +++ b/src/Services/Basket/Basket.FunctionalTests/Base/AutoAuthorizeMiddleware.cs @@ -1,31 +1,26 @@ -using Microsoft.AspNetCore.Http; -using System.Security.Claims; -using System.Threading.Tasks; +namespace Basket.FunctionalTests.Base; -namespace Basket.FunctionalTests.Base +class AutoAuthorizeMiddleware { - class AutoAuthorizeMiddleware - { - public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"; + public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"; - private readonly RequestDelegate _next; + private readonly RequestDelegate _next; - public AutoAuthorizeMiddleware(RequestDelegate rd) - { - _next = rd; - } + public AutoAuthorizeMiddleware(RequestDelegate rd) + { + _next = rd; + } - public async Task Invoke(HttpContext httpContext) - { - var identity = new ClaimsIdentity("cookies"); + public async Task Invoke(HttpContext httpContext) + { + var identity = new ClaimsIdentity("cookies"); - identity.AddClaim(new Claim("sub", IDENTITY_ID)); - identity.AddClaim(new Claim("unique_name", IDENTITY_ID)); - identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID)); + identity.AddClaim(new Claim("sub", IDENTITY_ID)); + identity.AddClaim(new Claim("unique_name", IDENTITY_ID)); + identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID)); - httpContext.User.AddIdentity(identity); + httpContext.User.AddIdentity(identity); - await _next.Invoke(httpContext); - } + await _next.Invoke(httpContext); } } diff --git a/src/Services/Basket/Basket.FunctionalTests/Base/BasketScenarioBase.cs b/src/Services/Basket/Basket.FunctionalTests/Base/BasketScenarioBase.cs index b5a62ce9d..b50b58bbd 100644 --- a/src/Services/Basket/Basket.FunctionalTests/Base/BasketScenarioBase.cs +++ b/src/Services/Basket/Basket.FunctionalTests/Base/BasketScenarioBase.cs @@ -1,43 +1,36 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using System.IO; -using System.Reflection; +namespace Basket.FunctionalTests.Base; -namespace Basket.FunctionalTests.Base +public class BasketScenarioBase { - public class BasketScenarioBase - { - private const string ApiUrlBase = "api/v1/basket"; + private const string ApiUrlBase = "api/v1/basket"; - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(BasketScenarioBase)) - .Location; + public TestServer CreateServer() + { + var path = Assembly.GetAssembly(typeof(BasketScenarioBase)) + .Location; - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("appsettings.json", optional: false) - .AddEnvironmentVariables(); - }).UseStartup(); + var hostBuilder = new WebHostBuilder() + .UseContentRoot(Path.GetDirectoryName(path)) + .ConfigureAppConfiguration(cb => + { + cb.AddJsonFile("appsettings.json", optional: false) + .AddEnvironmentVariables(); + }).UseStartup(); - return new TestServer(hostBuilder); - } + return new TestServer(hostBuilder); + } - public static class Get + public static class Get + { + public static string GetBasket(int id) { - public static string GetBasket(int id) - { - return $"{ApiUrlBase}/{id}"; - } + return $"{ApiUrlBase}/{id}"; } + } - public static class Post - { - public static string Basket = $"{ApiUrlBase}/"; - public static string CheckoutOrder = $"{ApiUrlBase}/checkout"; - } + public static class Post + { + public static string Basket = $"{ApiUrlBase}/"; + public static string CheckoutOrder = $"{ApiUrlBase}/checkout"; } } diff --git a/src/Services/Basket/Basket.FunctionalTests/Base/BasketTestStartup.cs b/src/Services/Basket/Basket.FunctionalTests/Base/BasketTestStartup.cs index d0237407d..b19d825cd 100644 --- a/src/Services/Basket/Basket.FunctionalTests/Base/BasketTestStartup.cs +++ b/src/Services/Basket/Basket.FunctionalTests/Base/BasketTestStartup.cs @@ -1,9 +1,4 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; -using Microsoft.eShopOnContainers.Services.Basket.API; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using System; + namespace Basket.FunctionalTests.Base { diff --git a/src/Services/Basket/Basket.FunctionalTests/Base/HttpClientExtensions.cs b/src/Services/Basket/Basket.FunctionalTests/Base/HttpClientExtensions.cs index f2da0b13e..45910df14 100644 --- a/src/Services/Basket/Basket.FunctionalTests/Base/HttpClientExtensions.cs +++ b/src/Services/Basket/Basket.FunctionalTests/Base/HttpClientExtensions.cs @@ -1,18 +1,13 @@ -using Microsoft.AspNetCore.TestHost; -using System; -using System.Net.Http; +namespace Basket.FunctionalTests.Base; -namespace Basket.FunctionalTests.Base +static class HttpClientExtensions { - static class HttpClientExtensions + public static HttpClient CreateIdempotentClient(this TestServer server) { - public static HttpClient CreateIdempotentClient(this TestServer server) - { - var client = server.CreateClient(); + var client = server.CreateClient(); - client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); + client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); - return client; - } + return client; } } diff --git a/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj b/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj index 9c8edeff2..db0b48fdb 100644 --- a/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj +++ b/src/Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false @@ -16,8 +16,9 @@ - - + + + diff --git a/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs b/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs index 6928d5cd2..f727b999e 100644 --- a/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs +++ b/src/Services/Basket/Basket.FunctionalTests/BasketScenarios.cs @@ -1,95 +1,79 @@ -using Basket.FunctionalTests.Base; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Newtonsoft.Json; -using System; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Xunit; +namespace Basket.FunctionalTests; -namespace Basket.FunctionalTests +public class BasketScenarios + : BasketScenarioBase { - public class BasketScenarios - : BasketScenarioBase + [Fact] + public async Task Post_basket_and_response_ok_status_code() { - [Fact] - public async Task Post_basket_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateClient() - .PostAsync(Post.Basket, content); + using var server = CreateServer(); + var content = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateClient() + .PostAsync(Post.Basket, content); - response.EnsureSuccessStatusCode(); - } - } + response.EnsureSuccessStatusCode(); + } - [Fact] - public async Task Get_basket_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.GetBasket(1)); + [Fact] + public async Task Get_basket_and_response_ok_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.GetBasket(1)); - response.EnsureSuccessStatusCode(); - } - } + response.EnsureSuccessStatusCode(); + } - [Fact] - public async Task Send_Checkout_basket_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + [Fact] + public async Task Send_Checkout_basket_and_response_ok_status_code() + { + using var server = CreateServer(); + var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); - await server.CreateClient() - .PostAsync(Post.Basket, contentBasket); + await server.CreateClient() + .PostAsync(Post.Basket, contentBasket); - var contentCheckout = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); + var contentCheckout = new StringContent(BuildCheckout(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateIdempotentClient() - .PostAsync(Post.CheckoutOrder, contentCheckout); + var response = await server.CreateIdempotentClient() + .PostAsync(Post.CheckoutOrder, contentCheckout); - response.EnsureSuccessStatusCode(); - } - } + response.EnsureSuccessStatusCode(); + } - string BuildBasket() - { - var order = new CustomerBasket(AutoAuthorizeMiddleware.IDENTITY_ID); + string BuildBasket() + { + var order = new CustomerBasket(AutoAuthorizeMiddleware.IDENTITY_ID); - order.Items.Add(new BasketItem - { - ProductId = 1, - ProductName = ".NET Bot Black Hoodie", - UnitPrice = 10, - Quantity = 1 - }); + order.Items.Add(new BasketItem + { + ProductId = 1, + ProductName = ".NET Bot Black Hoodie", + UnitPrice = 10, + Quantity = 1 + }); - return JsonConvert.SerializeObject(order); - } + return JsonSerializer.Serialize(order); + } - string BuildCheckout() + string BuildCheckout() + { + var checkoutBasket = new { - var checkoutBasket = new - { - City = "city", - Street = "street", - State = "state", - Country = "coutry", - ZipCode = "zipcode", - CardNumber = "1234567890123456", - CardHolderName = "CardHolderName", - CardExpiration = DateTime.UtcNow.AddDays(1), - CardSecurityNumber = "123", - CardTypeId = 1, - Buyer = "Buyer", - RequestId = Guid.NewGuid() - }; + City = "city", + Street = "street", + State = "state", + Country = "coutry", + ZipCode = "zipcode", + CardNumber = "1234567890123456", + CardHolderName = "CardHolderName", + CardExpiration = DateTime.UtcNow.AddDays(1), + CardSecurityNumber = "123", + CardTypeId = 1, + Buyer = "Buyer", + RequestId = Guid.NewGuid() + }; - return JsonConvert.SerializeObject(checkoutBasket); - } + return JsonSerializer.Serialize(checkoutBasket); } } diff --git a/src/Services/Basket/Basket.FunctionalTests/GlobalUsings.cs b/src/Services/Basket/Basket.FunctionalTests/GlobalUsings.cs new file mode 100644 index 000000000..d3657c2d3 --- /dev/null +++ b/src/Services/Basket/Basket.FunctionalTests/GlobalUsings.cs @@ -0,0 +1,23 @@ +global using Basket.FunctionalTests.Base; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Routing; +global using Microsoft.AspNetCore.TestHost; +global using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; +global using Microsoft.eShopOnContainers.Services.Basket.API.Model; +global using Microsoft.eShopOnContainers.Services.Basket.API; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using StackExchange.Redis; +global using System.Collections.Generic; +global using System.IO; +global using System.Net.Http; +global using System.Reflection; +global using System.Security.Claims; +global using System.Text.Json; +global using System.Text; +global using System.Threading.Tasks; +global using System; +global using Xunit; diff --git a/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs b/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs index a13c1f6a2..0a0cb11fa 100644 --- a/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs +++ b/src/Services/Basket/Basket.FunctionalTests/RedisBasketRepositoryTests.cs @@ -1,12 +1,4 @@ -using Basket.FunctionalTests.Base; -using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using StackExchange.Redis; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; + namespace Basket.FunctionalTests { @@ -17,21 +9,19 @@ namespace Basket.FunctionalTests [Fact] public async Task UpdateBasket_return_and_add_basket() { - using (var server = CreateServer()) - { - var redis = server.Host.Services.GetRequiredService(); + using var server = CreateServer(); + var redis = server.Host.Services.GetRequiredService(); - var redisBasketRepository = BuildBasketRepository(redis); + var redisBasketRepository = BuildBasketRepository(redis); - var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") - { - BuyerId = "buyerId", - Items = BuildBasketItems() - }); + var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") + { + BuyerId = "buyerId", + Items = BuildBasketItems() + }); - Assert.NotNull(basket); - Assert.Single(basket.Items); - } + Assert.NotNull(basket); + Assert.Single(basket.Items); } @@ -40,25 +30,23 @@ namespace Basket.FunctionalTests public async Task Delete_Basket_return_null() { - using (var server = CreateServer()) - { - var redis = server.Host.Services.GetRequiredService(); + using var server = CreateServer(); + var redis = server.Host.Services.GetRequiredService(); - var redisBasketRepository = BuildBasketRepository(redis); + var redisBasketRepository = BuildBasketRepository(redis); - var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") - { - BuyerId = "buyerId", - Items = BuildBasketItems() - }); + var basket = await redisBasketRepository.UpdateBasketAsync(new CustomerBasket("customerId") + { + BuyerId = "buyerId", + Items = BuildBasketItems() + }); - var deleteResult = await redisBasketRepository.DeleteBasketAsync("buyerId"); + var deleteResult = await redisBasketRepository.DeleteBasketAsync("buyerId"); - var result = await redisBasketRepository.GetBasketAsync(basket.BuyerId); + var result = await redisBasketRepository.GetBasketAsync(basket.BuyerId); - Assert.True(deleteResult); - Assert.Null(result); - } + Assert.True(deleteResult); + Assert.Null(result); } RedisBasketRepository BuildBasketRepository(ConnectionMultiplexer connMux) diff --git a/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs b/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs index 000183dec..89f1c2b33 100644 --- a/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs +++ b/src/Services/Basket/Basket.UnitTests/Application/BasketWebApiTest.cs @@ -1,155 +1,140 @@ -using Basket.API.IntegrationEvents.Events; -using Basket.API.Model; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.Services.Basket.API.Controllers; +namespace UnitTest.Basket.Application; + using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.Extensions.Logging; -using Moq; -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Threading.Tasks; -using Xunit; -using IBasketIdentityService = Microsoft.eShopOnContainers.Services.Basket.API.Services.IIdentityService; - -namespace UnitTest.Basket.Application + +public class BasketWebApiTest { - public class BasketWebApiTest + private readonly Mock _basketRepositoryMock; + private readonly Mock _identityServiceMock; + private readonly Mock _serviceBusMock; + private readonly Mock> _loggerMock; + + public BasketWebApiTest() { - private readonly Mock _basketRepositoryMock; - private readonly Mock _identityServiceMock; - private readonly Mock _serviceBusMock; - private readonly Mock> _loggerMock; + _basketRepositoryMock = new Mock(); + _identityServiceMock = new Mock(); + _serviceBusMock = new Mock(); + _loggerMock = new Mock>(); + } - public BasketWebApiTest() - { - _basketRepositoryMock = new Mock(); - _identityServiceMock = new Mock(); - _serviceBusMock = new Mock(); - _loggerMock = new Mock>(); - } - - [Fact] - public async Task Get_customer_basket_success() - { - //Arrange - var fakeCustomerId = "1"; - var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + [Fact] + public async Task Get_customer_basket_success() + { + //Arrange + var fakeCustomerId = "1"; + var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); - _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) - .Returns(Task.FromResult(fakeCustomerBasket)); - _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) + .Returns(Task.FromResult(fakeCustomerBasket)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); - _serviceBusMock.Setup(x => x.Publish(It.IsAny())); + _serviceBusMock.Setup(x => x.Publish(It.IsAny())); - //Act - var basketController = new BasketController( - _loggerMock.Object, - _basketRepositoryMock.Object, - _identityServiceMock.Object, - _serviceBusMock.Object); + //Act + var basketController = new BasketController( + _loggerMock.Object, + _basketRepositoryMock.Object, + _identityServiceMock.Object, + _serviceBusMock.Object); - var actionResult = await basketController.GetBasketByIdAsync(fakeCustomerId); + var actionResult = await basketController.GetBasketByIdAsync(fakeCustomerId); - //Assert - Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); - Assert.Equal((((ObjectResult)actionResult.Result).Value as CustomerBasket).BuyerId, fakeCustomerId); - } + //Assert + Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); + Assert.Equal((((ObjectResult)actionResult.Result).Value as CustomerBasket).BuyerId, fakeCustomerId); + } - [Fact] - public async Task Post_customer_basket_success() - { - //Arrange - var fakeCustomerId = "1"; - var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + [Fact] + public async Task Post_customer_basket_success() + { + //Arrange + var fakeCustomerId = "1"; + var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + + _basketRepositoryMock.Setup(x => x.UpdateBasketAsync(It.IsAny())) + .Returns(Task.FromResult(fakeCustomerBasket)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + _serviceBusMock.Setup(x => x.Publish(It.IsAny())); + + //Act + var basketController = new BasketController( + _loggerMock.Object, + _basketRepositoryMock.Object, + _identityServiceMock.Object, + _serviceBusMock.Object); + + var actionResult = await basketController.UpdateBasketAsync(fakeCustomerBasket); + + //Assert + Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); + Assert.Equal((((ObjectResult)actionResult.Result).Value as CustomerBasket).BuyerId, fakeCustomerId); + } - _basketRepositoryMock.Setup(x => x.UpdateBasketAsync(It.IsAny())) - .Returns(Task.FromResult(fakeCustomerBasket)); - _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); - _serviceBusMock.Setup(x => x.Publish(It.IsAny())); + [Fact] + public async Task Doing_Checkout_Without_Basket_Should_Return_Bad_Request() + { + var fakeCustomerId = "2"; + _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) + .Returns(Task.FromResult((CustomerBasket)null)); + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + + //Act + var basketController = new BasketController( + _loggerMock.Object, + _basketRepositoryMock.Object, + _identityServiceMock.Object, + _serviceBusMock.Object); + + var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult; + Assert.NotNull(result); + } - //Act - var basketController = new BasketController( - _loggerMock.Object, - _basketRepositoryMock.Object, - _identityServiceMock.Object, - _serviceBusMock.Object); + [Fact] + public async Task Doing_Checkout_Wit_Basket_Should_Publish_UserCheckoutAccepted_Integration_Event() + { + var fakeCustomerId = "1"; + var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); - var actionResult = await basketController.UpdateBasketAsync(fakeCustomerBasket); + _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) + .Returns(Task.FromResult(fakeCustomerBasket)); - //Assert - Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); - Assert.Equal((((ObjectResult)actionResult.Result).Value as CustomerBasket).BuyerId, fakeCustomerId); - } + _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); - [Fact] - public async Task Doing_Checkout_Without_Basket_Should_Return_Bad_Request() - { - var fakeCustomerId = "2"; - _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) - .Returns(Task.FromResult((CustomerBasket)null)); - _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); - - //Act - var basketController = new BasketController( - _loggerMock.Object, - _basketRepositoryMock.Object, - _identityServiceMock.Object, - _serviceBusMock.Object); - - var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as BadRequestResult; - Assert.NotNull(result); - } - - [Fact] - public async Task Doing_Checkout_Wit_Basket_Should_Publish_UserCheckoutAccepted_Integration_Event() + var basketController = new BasketController( + _loggerMock.Object, + _basketRepositoryMock.Object, + _identityServiceMock.Object, + _serviceBusMock.Object); + + basketController.ControllerContext = new ControllerContext() { - var fakeCustomerId = "1"; - var fakeCustomerBasket = GetCustomerBasketFake(fakeCustomerId); + HttpContext = new DefaultHttpContext() + { + User = new ClaimsPrincipal( + new ClaimsIdentity(new Claim[] { + new Claim("sub", "testuser"), + new Claim("unique_name", "testuser"), + new Claim(ClaimTypes.Name, "testuser") + })) + } + }; - _basketRepositoryMock.Setup(x => x.GetBasketAsync(It.IsAny())) - .Returns(Task.FromResult(fakeCustomerBasket)); + //Act + var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as AcceptedResult; - _identityServiceMock.Setup(x => x.GetUserIdentity()).Returns(fakeCustomerId); + _serviceBusMock.Verify(mock => mock.Publish(It.IsAny()), Times.Once); - var basketController = new BasketController( - _loggerMock.Object, - _basketRepositoryMock.Object, - _identityServiceMock.Object, - _serviceBusMock.Object); + Assert.NotNull(result); + } - basketController.ControllerContext = new ControllerContext() - { - HttpContext = new DefaultHttpContext() - { - User = new ClaimsPrincipal( - new ClaimsIdentity(new Claim[] { - new Claim("sub", "testuser"), - new Claim("unique_name", "testuser"), - new Claim(ClaimTypes.Name, "testuser") - })) - } - }; - - //Act - var result = await basketController.CheckoutAsync(new BasketCheckout(), Guid.NewGuid().ToString()) as AcceptedResult; - - _serviceBusMock.Verify(mock => mock.Publish(It.IsAny()), Times.Once); - - Assert.NotNull(result); - } - - private CustomerBasket GetCustomerBasketFake(string fakeCustomerId) + private CustomerBasket GetCustomerBasketFake(string fakeCustomerId) + { + return new CustomerBasket(fakeCustomerId) { - return new CustomerBasket(fakeCustomerId) + Items = new List() { - Items = new List() - { - new BasketItem() - } - }; - } + new BasketItem() + } + }; } } diff --git a/src/Services/Basket/Basket.UnitTests/Application/CartControllerTest.cs b/src/Services/Basket/Basket.UnitTests/Application/CartControllerTest.cs index bdbf8afd4..4231d6a9e 100644 --- a/src/Services/Basket/Basket.UnitTests/Application/CartControllerTest.cs +++ b/src/Services/Basket/Basket.UnitTests/Application/CartControllerTest.cs @@ -1,130 +1,117 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Controllers; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Moq; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Xunit; -using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; - -namespace UnitTest.Basket.Application +namespace UnitTest.Basket.Application; + +public class CartControllerTest { - public class CartControllerTest + private readonly Mock _catalogServiceMock; + private readonly Mock _basketServiceMock; + private readonly Mock> _identityParserMock; + private readonly Mock _contextMock; + + public CartControllerTest() { - private readonly Mock _catalogServiceMock; - private readonly Mock _basketServiceMock; - private readonly Mock> _identityParserMock; - private readonly Mock _contextMock; + _catalogServiceMock = new Mock(); + _basketServiceMock = new Mock(); + _identityParserMock = new Mock>(); + _contextMock = new Mock(); + } - public CartControllerTest() - { - _catalogServiceMock = new Mock(); - _basketServiceMock = new Mock(); - _identityParserMock = new Mock>(); - _contextMock = new Mock(); - } - - [Fact] - public async Task Post_cart_success() - { - //Arrange - var fakeBuyerId = "1"; - var action = string.Empty; - var fakeBasket = GetFakeBasket(fakeBuyerId); - var fakeQuantities = new Dictionary() - { - ["fakeProdA"] = 1, - ["fakeProdB"] = 2 - }; - - _basketServiceMock.Setup(x => x.SetQuantities(It.IsAny(), It.IsAny>())) - .Returns(Task.FromResult(fakeBasket)); - - _basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny())) - .Returns(Task.FromResult(fakeBasket)); - - //Act - var cartController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); - cartController.ControllerContext.HttpContext = _contextMock.Object; - var actionResult = await cartController.Index(fakeQuantities, action); - - //Assert - var viewResult = Assert.IsType(actionResult); - } - - [Fact] - public async Task Post_cart_checkout_success() + [Fact] + public async Task Post_cart_success() + { + //Arrange + var fakeBuyerId = "1"; + var action = string.Empty; + var fakeBasket = GetFakeBasket(fakeBuyerId); + var fakeQuantities = new Dictionary() { - //Arrange - var fakeBuyerId = "1"; - var action = "[ Checkout ]"; - var fakeBasket = GetFakeBasket(fakeBuyerId); - var fakeQuantities = new Dictionary() - { - ["fakeProdA"] = 1, - ["fakeProdB"] = 2 - }; - - _basketServiceMock.Setup(x => x.SetQuantities(It.IsAny(), It.IsAny>())) - .Returns(Task.FromResult(fakeBasket)); - - _basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny())) - .Returns(Task.FromResult(fakeBasket)); - - //Act - var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); - orderController.ControllerContext.HttpContext = _contextMock.Object; - var actionResult = await orderController.Index(fakeQuantities, action); - - //Assert - var redirectToActionResult = Assert.IsType(actionResult); - Assert.Equal("Order", redirectToActionResult.ControllerName); - Assert.Equal("Create", redirectToActionResult.ActionName); - } - - [Fact] - public async Task Add_to_cart_success() + ["fakeProdA"] = 1, + ["fakeProdB"] = 2 + }; + + _basketServiceMock.Setup(x => x.SetQuantities(It.IsAny(), It.IsAny>())) + .Returns(Task.FromResult(fakeBasket)); + + _basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny())) + .Returns(Task.FromResult(fakeBasket)); + + //Act + var cartController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); + cartController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await cartController.Index(fakeQuantities, action); + + //Assert + var viewResult = Assert.IsType(actionResult); + } + + [Fact] + public async Task Post_cart_checkout_success() + { + //Arrange + var fakeBuyerId = "1"; + var action = "[ Checkout ]"; + var fakeBasket = GetFakeBasket(fakeBuyerId); + var fakeQuantities = new Dictionary() { - //Arrange - var fakeCatalogItem = GetFakeCatalogItem(); + ["fakeProdA"] = 1, + ["fakeProdB"] = 2 + }; + + _basketServiceMock.Setup(x => x.SetQuantities(It.IsAny(), It.IsAny>())) + .Returns(Task.FromResult(fakeBasket)); + + _basketServiceMock.Setup(x => x.UpdateBasket(It.IsAny())) + .Returns(Task.FromResult(fakeBasket)); + + //Act + var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); + orderController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await orderController.Index(fakeQuantities, action); + + //Assert + var redirectToActionResult = Assert.IsType(actionResult); + Assert.Equal("Order", redirectToActionResult.ControllerName); + Assert.Equal("Create", redirectToActionResult.ActionName); + } - _basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny(), It.IsAny())) - .Returns(Task.FromResult(1)); + [Fact] + public async Task Add_to_cart_success() + { + //Arrange + var fakeCatalogItem = GetFakeCatalogItem(); + + _basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny(), It.IsAny())) + .Returns(Task.FromResult(1)); - //Act - var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); - orderController.ControllerContext.HttpContext = _contextMock.Object; - var actionResult = await orderController.AddToCart(fakeCatalogItem); + //Act + var orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object); + orderController.ControllerContext.HttpContext = _contextMock.Object; + var actionResult = await orderController.AddToCart(fakeCatalogItem); - //Assert - var redirectToActionResult = Assert.IsType(actionResult); - Assert.Equal("Catalog", redirectToActionResult.ControllerName); - Assert.Equal("Index", redirectToActionResult.ActionName); - } + //Assert + var redirectToActionResult = Assert.IsType(actionResult); + Assert.Equal("Catalog", redirectToActionResult.ControllerName); + Assert.Equal("Index", redirectToActionResult.ActionName); + } - private BasketModel GetFakeBasket(string buyerId) + private BasketModel GetFakeBasket(string buyerId) + { + return new BasketModel() { - return new BasketModel() - { - BuyerId = buyerId - }; - } + BuyerId = buyerId + }; + } - private CatalogItem GetFakeCatalogItem() + private CatalogItem GetFakeCatalogItem() + { + return new CatalogItem() { - return new CatalogItem() - { - Id = 1, - Name = "fakeName", - CatalogBrand = "fakeBrand", - CatalogType = "fakeType", - CatalogBrandId = 2, - CatalogTypeId = 5, - Price = 20 - }; - } + Id = 1, + Name = "fakeName", + CatalogBrand = "fakeBrand", + CatalogType = "fakeType", + CatalogBrandId = 2, + CatalogTypeId = 5, + Price = 20 + }; } } diff --git a/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj b/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj index 1a3ec830e..039258c2f 100644 --- a/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj +++ b/src/Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj @@ -1,15 +1,15 @@  - net5.0 + net6.0 false false - - + + diff --git a/src/Services/Basket/Basket.UnitTests/GlobalUsings.cs b/src/Services/Basket/Basket.UnitTests/GlobalUsings.cs new file mode 100644 index 000000000..6e5443b74 --- /dev/null +++ b/src/Services/Basket/Basket.UnitTests/GlobalUsings.cs @@ -0,0 +1,19 @@ +global using Basket.API.IntegrationEvents.Events; +global using Basket.API.Model; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.Services.Basket.API.Controllers; +global using Microsoft.eShopOnContainers.Services.Basket.API.Model; +global using Microsoft.Extensions.Logging; +global using Moq; +global using System; +global using System.Collections.Generic; +global using System.Security.Claims; +global using System.Threading.Tasks; +global using Xunit; +global using IBasketIdentityService = Microsoft.eShopOnContainers.Services.Basket.API.Services.IIdentityService; +global using Microsoft.eShopOnContainers.WebMVC.Controllers; +global using Microsoft.eShopOnContainers.WebMVC.Services; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels; +global using BasketModel = Microsoft.eShopOnContainers.WebMVC.ViewModels.Basket; diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index 5ba3b6132..b78ce2af3 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 portable true Catalog.API @@ -9,8 +9,7 @@ aspnet-Catalog.API-20161122013618 ..\..\..\..\docker-compose.dcproj false - true - preview + true @@ -42,30 +41,37 @@ - + + + - + - - + + - - - + + + - - - - - - - - + + + + + + + + + - - + + + + + + diff --git a/src/Services/Catalog/Catalog.API/CatalogSettings.cs b/src/Services/Catalog/Catalog.API/CatalogSettings.cs index 297c68914..2fba164a0 100644 --- a/src/Services/Catalog/Catalog.API/CatalogSettings.cs +++ b/src/Services/Catalog/Catalog.API/CatalogSettings.cs @@ -1,13 +1,12 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API +namespace Microsoft.eShopOnContainers.Services.Catalog.API; + +public class CatalogSettings { - public class CatalogSettings - { - public string PicBaseUrl { get; set; } + public string PicBaseUrl { get; set; } - public string EventBusConnection { get; set; } + public string EventBusConnection { get; set; } - public bool UseCustomizationData { get; set; } + public bool UseCustomizationData { get; set; } - public bool AzureStorageEnabled { get; set; } - } + public bool AzureStorageEnabled { get; set; } } diff --git a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs index d58c06f66..4dd1143f6 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/CatalogController.cs @@ -1,315 +1,300 @@ -using Catalog.API.IntegrationEvents; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; -using Microsoft.eShopOnContainers.Services.Catalog.API.Model; -using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers; + +[Route("api/v1/[controller]")] +[ApiController] +public class CatalogController : ControllerBase { - [Route("api/v1/[controller]")] - [ApiController] - public class CatalogController : ControllerBase - { - private readonly CatalogContext _catalogContext; - private readonly CatalogSettings _settings; - private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; + private readonly CatalogContext _catalogContext; + private readonly CatalogSettings _settings; + private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; - public CatalogController(CatalogContext context, IOptionsSnapshot settings, ICatalogIntegrationEventService catalogIntegrationEventService) - { - _catalogContext = context ?? throw new ArgumentNullException(nameof(context)); - _catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService)); - _settings = settings.Value; + public CatalogController(CatalogContext context, IOptionsSnapshot settings, ICatalogIntegrationEventService catalogIntegrationEventService) + { + _catalogContext = context ?? throw new ArgumentNullException(nameof(context)); + _catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService)); + _settings = settings.Value; - context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - } + context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + } - // GET api/v1/[controller]/items[?pageSize=3&pageIndex=10] - [HttpGet] - [Route("items")] - [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] - [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - public async Task ItemsAsync([FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0, string ids = null) + // GET api/v1/[controller]/items[?pageSize=3&pageIndex=10] + [HttpGet] + [Route("items")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + public async Task ItemsAsync([FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0, string ids = null) + { + if (!string.IsNullOrEmpty(ids)) { - if (!string.IsNullOrEmpty(ids)) - { - var items = await GetItemsByIdsAsync(ids); - - if (!items.Any()) - { - return BadRequest("ids value invalid. Must be comma-separated list of numbers"); - } + var items = await GetItemsByIdsAsync(ids); - return Ok(items); + if (!items.Any()) + { + return BadRequest("ids value invalid. Must be comma-separated list of numbers"); } - var totalItems = await _catalogContext.CatalogItems - .LongCountAsync(); - - var itemsOnPage = await _catalogContext.CatalogItems - .OrderBy(c => c.Name) - .Skip(pageSize * pageIndex) - .Take(pageSize) - .ToListAsync(); - - /* The "awesome" fix for testing Devspaces */ - - /* - foreach (var pr in itemsOnPage) { - pr.Name = "Awesome " + pr.Name; - } + return Ok(items); + } - */ + var totalItems = await _catalogContext.CatalogItems + .LongCountAsync(); - itemsOnPage = ChangeUriPlaceholder(itemsOnPage); + var itemsOnPage = await _catalogContext.CatalogItems + .OrderBy(c => c.Name) + .Skip(pageSize * pageIndex) + .Take(pageSize) + .ToListAsync(); - var model = new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); + /* The "awesome" fix for testing Devspaces */ - return Ok(model); + /* + foreach (var pr in itemsOnPage) { + pr.Name = "Awesome " + pr.Name; } - private async Task> GetItemsByIdsAsync(string ids) - { - var numIds = ids.Split(',').Select(id => (Ok: int.TryParse(id, out int x), Value: x)); + */ - if (!numIds.All(nid => nid.Ok)) - { - return new List(); - } + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); - var idsToSelect = numIds - .Select(id => id.Value); + var model = new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); - var items = await _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToListAsync(); - - items = ChangeUriPlaceholder(items); + return Ok(model); + } - return items; - } + private async Task> GetItemsByIdsAsync(string ids) + { + var numIds = ids.Split(',').Select(id => (Ok: int.TryParse(id, out int x), Value: x)); - [HttpGet] - [Route("items/{id:int}")] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(typeof(CatalogItem), (int)HttpStatusCode.OK)] - public async Task> ItemByIdAsync(int id) + if (!numIds.All(nid => nid.Ok)) { - if (id <= 0) - { - return BadRequest(); - } + return new List(); + } - var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(ci => ci.Id == id); + var idsToSelect = numIds + .Select(id => id.Value); - var baseUri = _settings.PicBaseUrl; - var azureStorageEnabled = _settings.AzureStorageEnabled; + var items = await _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToListAsync(); - item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); + items = ChangeUriPlaceholder(items); - if (item != null) - { - return item; - } + return items; + } - return NotFound(); + [HttpGet] + [Route("items/{id:int}")] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(typeof(CatalogItem), (int)HttpStatusCode.OK)] + public async Task> ItemByIdAsync(int id) + { + if (id <= 0) + { + return BadRequest(); } - // GET api/v1/[controller]/items/withname/samplename[?pageSize=3&pageIndex=10] - [HttpGet] - [Route("items/withname/{name:minlength(1)}")] - [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] - public async Task>> ItemsWithNameAsync(string name, [FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0) - { - var totalItems = await _catalogContext.CatalogItems - .Where(c => c.Name.StartsWith(name)) - .LongCountAsync(); + var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(ci => ci.Id == id); - var itemsOnPage = await _catalogContext.CatalogItems - .Where(c => c.Name.StartsWith(name)) - .Skip(pageSize * pageIndex) - .Take(pageSize) - .ToListAsync(); + var baseUri = _settings.PicBaseUrl; + var azureStorageEnabled = _settings.AzureStorageEnabled; - itemsOnPage = ChangeUriPlaceholder(itemsOnPage); + item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); - return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); + if (item != null) + { + return item; } - // GET api/v1/[controller]/items/type/1/brand[?pageSize=3&pageIndex=10] - [HttpGet] - [Route("items/type/{catalogTypeId}/brand/{catalogBrandId:int?}")] - [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] - public async Task>> ItemsByTypeIdAndBrandIdAsync(int catalogTypeId, int? catalogBrandId, [FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0) - { - var root = (IQueryable)_catalogContext.CatalogItems; + return NotFound(); + } - root = root.Where(ci => ci.CatalogTypeId == catalogTypeId); + // GET api/v1/[controller]/items/withname/samplename[?pageSize=3&pageIndex=10] + [HttpGet] + [Route("items/withname/{name:minlength(1)}")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] + public async Task>> ItemsWithNameAsync(string name, [FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0) + { + var totalItems = await _catalogContext.CatalogItems + .Where(c => c.Name.StartsWith(name)) + .LongCountAsync(); - if (catalogBrandId.HasValue) - { - root = root.Where(ci => ci.CatalogBrandId == catalogBrandId); - } + var itemsOnPage = await _catalogContext.CatalogItems + .Where(c => c.Name.StartsWith(name)) + .Skip(pageSize * pageIndex) + .Take(pageSize) + .ToListAsync(); - var totalItems = await root - .LongCountAsync(); + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); - var itemsOnPage = await root - .Skip(pageSize * pageIndex) - .Take(pageSize) - .ToListAsync(); + return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); + } - itemsOnPage = ChangeUriPlaceholder(itemsOnPage); + // GET api/v1/[controller]/items/type/1/brand[?pageSize=3&pageIndex=10] + [HttpGet] + [Route("items/type/{catalogTypeId}/brand/{catalogBrandId:int?}")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] + public async Task>> ItemsByTypeIdAndBrandIdAsync(int catalogTypeId, int? catalogBrandId, [FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0) + { + var root = (IQueryable)_catalogContext.CatalogItems; - return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); - } + root = root.Where(ci => ci.CatalogTypeId == catalogTypeId); - // GET api/v1/[controller]/items/type/all/brand[?pageSize=3&pageIndex=10] - [HttpGet] - [Route("items/type/all/brand/{catalogBrandId:int?}")] - [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] - public async Task>> ItemsByBrandIdAsync(int? catalogBrandId, [FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0) + if (catalogBrandId.HasValue) { - var root = (IQueryable)_catalogContext.CatalogItems; - - if (catalogBrandId.HasValue) - { - root = root.Where(ci => ci.CatalogBrandId == catalogBrandId); - } + root = root.Where(ci => ci.CatalogBrandId == catalogBrandId); + } - var totalItems = await root - .LongCountAsync(); + var totalItems = await root + .LongCountAsync(); - var itemsOnPage = await root - .Skip(pageSize * pageIndex) - .Take(pageSize) - .ToListAsync(); + var itemsOnPage = await root + .Skip(pageSize * pageIndex) + .Take(pageSize) + .ToListAsync(); - itemsOnPage = ChangeUriPlaceholder(itemsOnPage); + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); - return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); - } + return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); + } - // GET api/v1/[controller]/CatalogTypes - [HttpGet] - [Route("catalogtypes")] - [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] - public async Task>> CatalogTypesAsync() - { - return await _catalogContext.CatalogTypes.ToListAsync(); - } + // GET api/v1/[controller]/items/type/all/brand[?pageSize=3&pageIndex=10] + [HttpGet] + [Route("items/type/all/brand/{catalogBrandId:int?}")] + [ProducesResponseType(typeof(PaginatedItemsViewModel), (int)HttpStatusCode.OK)] + public async Task>> ItemsByBrandIdAsync(int? catalogBrandId, [FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0) + { + var root = (IQueryable)_catalogContext.CatalogItems; - // GET api/v1/[controller]/CatalogBrands - [HttpGet] - [Route("catalogbrands")] - [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] - public async Task>> CatalogBrandsAsync() + if (catalogBrandId.HasValue) { - return await _catalogContext.CatalogBrands.ToListAsync(); + root = root.Where(ci => ci.CatalogBrandId == catalogBrandId); } - //PUT api/v1/[controller]/items - [Route("items")] - [HttpPut] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - [ProducesResponseType((int)HttpStatusCode.Created)] - public async Task UpdateProductAsync([FromBody] CatalogItem productToUpdate) - { - var catalogItem = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id); + var totalItems = await root + .LongCountAsync(); - if (catalogItem == null) - { - return NotFound(new { Message = $"Item with id {productToUpdate.Id} not found." }); - } + var itemsOnPage = await root + .Skip(pageSize * pageIndex) + .Take(pageSize) + .ToListAsync(); - var oldPrice = catalogItem.Price; - var raiseProductPriceChangedEvent = oldPrice != productToUpdate.Price; + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); - // Update current product - catalogItem = productToUpdate; - _catalogContext.CatalogItems.Update(catalogItem); + return new PaginatedItemsViewModel(pageIndex, pageSize, totalItems, itemsOnPage); + } - if (raiseProductPriceChangedEvent) // Save product's data and publish integration event through the Event Bus if price has changed - { - //Create Integration Event to be published through the Event Bus - var priceChangedEvent = new ProductPriceChangedIntegrationEvent(catalogItem.Id, productToUpdate.Price, oldPrice); + // GET api/v1/[controller]/CatalogTypes + [HttpGet] + [Route("catalogtypes")] + [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] + public async Task>> CatalogTypesAsync() + { + return await _catalogContext.CatalogTypes.ToListAsync(); + } - // Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction - await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(priceChangedEvent); + // GET api/v1/[controller]/CatalogBrands + [HttpGet] + [Route("catalogbrands")] + [ProducesResponseType(typeof(List), (int)HttpStatusCode.OK)] + public async Task>> CatalogBrandsAsync() + { + return await _catalogContext.CatalogBrands.ToListAsync(); + } - // Publish through the Event Bus and mark the saved event as published - await _catalogIntegrationEventService.PublishThroughEventBusAsync(priceChangedEvent); - } - else // Just save the updated product because the Product's Price hasn't changed. - { - await _catalogContext.SaveChangesAsync(); - } + //PUT api/v1/[controller]/items + [Route("items")] + [HttpPut] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.Created)] + public async Task UpdateProductAsync([FromBody] CatalogItem productToUpdate) + { + var catalogItem = await _catalogContext.CatalogItems.SingleOrDefaultAsync(i => i.Id == productToUpdate.Id); - return CreatedAtAction(nameof(ItemByIdAsync), new { id = productToUpdate.Id }, null); + if (catalogItem == null) + { + return NotFound(new { Message = $"Item with id {productToUpdate.Id} not found." }); } - //POST api/v1/[controller]/items - [Route("items")] - [HttpPost] - [ProducesResponseType((int)HttpStatusCode.Created)] - public async Task CreateProductAsync([FromBody] CatalogItem product) + var oldPrice = catalogItem.Price; + var raiseProductPriceChangedEvent = oldPrice != productToUpdate.Price; + + // Update current product + catalogItem = productToUpdate; + _catalogContext.CatalogItems.Update(catalogItem); + + if (raiseProductPriceChangedEvent) // Save product's data and publish integration event through the Event Bus if price has changed { - var item = new CatalogItem - { - CatalogBrandId = product.CatalogBrandId, - CatalogTypeId = product.CatalogTypeId, - Description = product.Description, - Name = product.Name, - PictureFileName = product.PictureFileName, - Price = product.Price - }; + //Create Integration Event to be published through the Event Bus + var priceChangedEvent = new ProductPriceChangedIntegrationEvent(catalogItem.Id, productToUpdate.Price, oldPrice); - _catalogContext.CatalogItems.Add(item); + // Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction + await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(priceChangedEvent); + // Publish through the Event Bus and mark the saved event as published + await _catalogIntegrationEventService.PublishThroughEventBusAsync(priceChangedEvent); + } + else // Just save the updated product because the Product's Price hasn't changed. + { await _catalogContext.SaveChangesAsync(); - - return CreatedAtAction(nameof(ItemByIdAsync), new { id = item.Id }, null); } - //DELETE api/v1/[controller]/id - [Route("{id}")] - [HttpDelete] - [ProducesResponseType((int)HttpStatusCode.NoContent)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task DeleteProductAsync(int id) + return CreatedAtAction(nameof(ItemByIdAsync), new { id = productToUpdate.Id }, null); + } + + //POST api/v1/[controller]/items + [Route("items")] + [HttpPost] + [ProducesResponseType((int)HttpStatusCode.Created)] + public async Task CreateProductAsync([FromBody] CatalogItem product) + { + var item = new CatalogItem { - var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id); + CatalogBrandId = product.CatalogBrandId, + CatalogTypeId = product.CatalogTypeId, + Description = product.Description, + Name = product.Name, + PictureFileName = product.PictureFileName, + Price = product.Price + }; - if (product == null) - { - return NotFound(); - } + _catalogContext.CatalogItems.Add(item); - _catalogContext.CatalogItems.Remove(product); + await _catalogContext.SaveChangesAsync(); - await _catalogContext.SaveChangesAsync(); + return CreatedAtAction(nameof(ItemByIdAsync), new { id = item.Id }, null); + } - return NoContent(); - } + //DELETE api/v1/[controller]/id + [Route("{id}")] + [HttpDelete] + [ProducesResponseType((int)HttpStatusCode.NoContent)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task DeleteProductAsync(int id) + { + var product = _catalogContext.CatalogItems.SingleOrDefault(x => x.Id == id); - private List ChangeUriPlaceholder(List items) + if (product == null) { - var baseUri = _settings.PicBaseUrl; - var azureStorageEnabled = _settings.AzureStorageEnabled; + return NotFound(); + } - foreach (var item in items) - { - item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); - } + _catalogContext.CatalogItems.Remove(product); + + await _catalogContext.SaveChangesAsync(); + + return NoContent(); + } - return items; + private List ChangeUriPlaceholder(List items) + { + var baseUri = _settings.PicBaseUrl; + var azureStorageEnabled = _settings.AzureStorageEnabled; + + foreach (var item in items) + { + item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); } + + return items; } } diff --git a/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs b/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs index 37792fb04..cd86a2966 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/HomeController.cs @@ -1,15 +1,11 @@ -using Microsoft.AspNetCore.Mvc; +// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers; -// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 - -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers +public class HomeController : Controller { - public class HomeController : Controller + // GET: // + public IActionResult Index() { - // GET: // - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } + return new RedirectResult("~/swagger"); } } diff --git a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs index 31c93683c..dfb6f0d03 100644 --- a/src/Services/Catalog/Catalog.API/Controllers/PicController.cs +++ b/src/Services/Catalog/Catalog.API/Controllers/PicController.cs @@ -1,96 +1,64 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using System.IO; -using System.Net; -using System.Threading.Tasks; +// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers; -// For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 - -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Controllers +[ApiController] +public class PicController : ControllerBase { - [ApiController] - public class PicController : ControllerBase + private readonly IWebHostEnvironment _env; + private readonly CatalogContext _catalogContext; + + public PicController(IWebHostEnvironment env, + CatalogContext catalogContext) { - private readonly IWebHostEnvironment _env; - private readonly CatalogContext _catalogContext; + _env = env; + _catalogContext = catalogContext; + } - public PicController(IWebHostEnvironment env, - CatalogContext catalogContext) + [HttpGet] + [Route("api/v1/catalog/items/{catalogItemId:int}/pic")] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + // GET: // + public async Task GetImageAsync(int catalogItemId) + { + if (catalogItemId <= 0) { - _env = env; - _catalogContext = catalogContext; + return BadRequest(); } - [HttpGet] - [Route("api/v1/catalog/items/{catalogItemId:int}/pic")] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - // GET: // - public async Task GetImageAsync(int catalogItemId) - { - if (catalogItemId <= 0) - { - return BadRequest(); - } - - var item = await _catalogContext.CatalogItems - .SingleOrDefaultAsync(ci => ci.Id == catalogItemId); - - if (item != null) - { - var webRoot = _env.WebRootPath; - var path = Path.Combine(webRoot, item.PictureFileName); + var item = await _catalogContext.CatalogItems + .SingleOrDefaultAsync(ci => ci.Id == catalogItemId); - string imageFileExtension = Path.GetExtension(item.PictureFileName); - string mimetype = GetImageMimeTypeFromImageFileExtension(imageFileExtension); + if (item != null) + { + var webRoot = _env.WebRootPath; + var path = Path.Combine(webRoot, item.PictureFileName); - var buffer = await System.IO.File.ReadAllBytesAsync(path); + string imageFileExtension = Path.GetExtension(item.PictureFileName); + string mimetype = GetImageMimeTypeFromImageFileExtension(imageFileExtension); - return File(buffer, mimetype); - } + var buffer = await System.IO.File.ReadAllBytesAsync(path); - return NotFound(); + return File(buffer, mimetype); } - private string GetImageMimeTypeFromImageFileExtension(string extension) - { - string mimetype; - - switch (extension) - { - case ".png": - mimetype = "image/png"; - break; - case ".gif": - mimetype = "image/gif"; - break; - case ".jpg": - case ".jpeg": - mimetype = "image/jpeg"; - break; - case ".bmp": - mimetype = "image/bmp"; - break; - case ".tiff": - mimetype = "image/tiff"; - break; - case ".wmf": - mimetype = "image/wmf"; - break; - case ".jp2": - mimetype = "image/jp2"; - break; - case ".svg": - mimetype = "image/svg+xml"; - break; - default: - mimetype = "application/octet-stream"; - break; - } + return NotFound(); + } - return mimetype; - } + private string GetImageMimeTypeFromImageFileExtension(string extension) + { + string mimetype = extension switch + { + ".png" => "image/png", + ".gif" => "image/gif", + ".jpg" or ".jpeg" => "image/jpeg", + ".bmp" => "image/bmp", + ".tiff" => "image/tiff", + ".wmf" => "image/wmf", + ".jp2" => "image/jp2", + ".svg" => "image/svg+xml", + _ => "application/octet-stream", + }; + return mimetype; } } diff --git a/src/Services/Catalog/Catalog.API/Dockerfile b/src/Services/Catalog/Catalog.API/Dockerfile index ec10cac79..e491c2110 100644 --- a/src/Services/Catalog/Catalog.API/Dockerfile +++ b/src/Services/Catalog/Catalog.API/Dockerfile @@ -1,9 +1,9 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -14,6 +14,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Catalog/Catalog.API/Dockerfile.develop b/src/Services/Catalog/Catalog.API/Dockerfile.develop index 3df91b3df..513396298 100644 --- a/src/Services/Catalog/Catalog.API/Dockerfile.develop +++ b/src/Services/Catalog/Catalog.API/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs index e953df581..efebc7615 100644 --- a/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs +++ b/src/Services/Catalog/Catalog.API/Extensions/CatalogItemExtensions.cs @@ -1,15 +1,14 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model; + +public static class CatalogItemExtensions { - public static class CatalogItemExtensions + public static void FillProductUrl(this CatalogItem item, string picBaseUrl, bool azureStorageEnabled) { - public static void FillProductUrl(this CatalogItem item, string picBaseUrl, bool azureStorageEnabled) + if (item != null) { - if (item != null) - { - item.PictureUri = azureStorageEnabled - ? picBaseUrl + item.PictureFileName - : picBaseUrl.Replace("[0]", item.Id.ToString()); - } + item.PictureUri = azureStorageEnabled + ? picBaseUrl + item.PictureFileName + : picBaseUrl.Replace("[0]", item.Id.ToString()); } } } diff --git a/src/Services/Catalog/Catalog.API/Extensions/HostExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/HostExtensions.cs deleted file mode 100644 index ccdd73558..000000000 --- a/src/Services/Catalog/Catalog.API/Extensions/HostExtensions.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Polly; -using System; -using System.Data.SqlClient; - -namespace Catalog.API.Extensions -{ - public static class HostExtensions - { - public static bool IsInKubernetes(this IHost host) - { - var cfg = host.Services.GetService(); - var orchestratorType = cfg.GetValue("OrchestratorType"); - return orchestratorType?.ToUpper() == "K8S"; - } - - public static IHost MigrateDbContext(this IHost host, Action seeder) where TContext : DbContext - { - var underK8s = host.IsInKubernetes(); - - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; - - var logger = services.GetRequiredService>(); - - var context = services.GetService(); - - try - { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retry = Policy.Handle() - .WaitAndRetry(new TimeSpan[] - { - TimeSpan.FromSeconds(3), - TimeSpan.FromSeconds(5), - TimeSpan.FromSeconds(8), - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } - - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); - } - catch (Exception ex) - { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } - } - } - - return host; - } - - private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) - where TContext : DbContext - { - context.Database.Migrate(); - seeder(context, services); - } - } -} diff --git a/src/Services/Catalog/Catalog.API/Extensions/LinqSelectExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/LinqSelectExtensions.cs index 1e5fbf789..85fa9300c 100644 --- a/src/Services/Catalog/Catalog.API/Extensions/LinqSelectExtensions.cs +++ b/src/Services/Catalog/Catalog.API/Extensions/LinqSelectExtensions.cs @@ -1,50 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Extensions; -namespace Catalog.API.Extensions +public static class LinqSelectExtensions { - public static class LinqSelectExtensions + public static IEnumerable> SelectTry(this IEnumerable enumerable, Func selector) { - public static IEnumerable> SelectTry(this IEnumerable enumerable, Func selector) + foreach (TSource element in enumerable) { - foreach (TSource element in enumerable) + SelectTryResult returnedValue; + try { - SelectTryResult returnedValue; - try - { - returnedValue = new SelectTryResult(element, selector(element), null); - } - catch (Exception ex) - { - returnedValue = new SelectTryResult(element, default(TResult), ex); - } - yield return returnedValue; + returnedValue = new SelectTryResult(element, selector(element), null); } + catch (Exception ex) + { + returnedValue = new SelectTryResult(element, default(TResult), ex); + } + yield return returnedValue; } + } - public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) - { - return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException)); - } + public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) + { + return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException)); + } - public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) - { - return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException)); - } + public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) + { + return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException)); + } - public class SelectTryResult + public class SelectTryResult + { + internal SelectTryResult(TSource source, TResult result, Exception exception) { - internal SelectTryResult(TSource source, TResult result, Exception exception) - { - Source = source; - Result = result; - CaughtException = exception; - } - - public TSource Source { get; private set; } - public TResult Result { get; private set; } - public Exception CaughtException { get; private set; } + Source = source; + Result = result; + CaughtException = exception; } + + public TSource Source { get; private set; } + public TResult Result { get; private set; } + public Exception CaughtException { get; private set; } } } diff --git a/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs b/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs index 07fc11770..588ca7a35 100644 --- a/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs +++ b/src/Services/Catalog/Catalog.API/Extensions/WebHostExtensions.cs @@ -1,80 +1,68 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Polly; -using System; -using System.Data.SqlClient; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Extensions; -namespace Catalog.API.Extensions +public static class WebHostExtensions { - public static class WebHostExtensions + public static bool IsInKubernetes(this IWebHost host) { - public static bool IsInKubernetes(this IWebHost host) - { - var cfg = host.Services.GetService(); - var orchestratorType = cfg.GetValue("OrchestratorType"); - return orchestratorType?.ToUpper() == "K8S"; - } - - public static IWebHost MigrateDbContext(this IWebHost host, Action seeder) where TContext : DbContext - { - var underK8s = host.IsInKubernetes(); + var cfg = host.Services.GetService(); + var orchestratorType = cfg.GetValue("OrchestratorType"); + return orchestratorType?.ToUpper() == "K8S"; + } - using (var scope = host.Services.CreateScope()) - { - var services = scope.ServiceProvider; + public static IWebHost MigrateDbContext(this IWebHost host, Action seeder) where TContext : DbContext + { + var underK8s = host.IsInKubernetes(); - var logger = services.GetRequiredService>(); + using var scope = host.Services.CreateScope(); + var services = scope.ServiceProvider; - var context = services.GetService(); + var logger = services.GetRequiredService>(); - try - { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); + var context = services.GetService(); - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retry = Policy.Handle() - .WaitAndRetry(new TimeSpan[] - { - TimeSpan.FromSeconds(3), - TimeSpan.FromSeconds(5), - TimeSpan.FromSeconds(8), - }); + try + { + logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } + if (underK8s) + { + InvokeSeeder(seeder, context, services); + } + else + { + var retry = Policy.Handle() + .WaitAndRetry(new TimeSpan[] + { + TimeSpan.FromSeconds(3), + TimeSpan.FromSeconds(5), + TimeSpan.FromSeconds(8), + }); - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); - } - catch (Exception ex) - { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } - } + //if the sql server container is not created on run docker compose this + //migration can't fail for network related exception. The retry options for DbContext only + //apply to transient exceptions + // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + retry.Execute(() => InvokeSeeder(seeder, context, services)); } - return host; + logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); } - - private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) - where TContext : DbContext + catch (Exception ex) { - context.Database.Migrate(); - seeder(context, services); + logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + if (underK8s) + { + throw; // Rethrow under k8s because we rely on k8s to re-run the pod + } } + + return host; + } + + private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) + where TContext : DbContext + { + context.Database.Migrate(); + seeder(context, services); } } diff --git a/src/Services/Catalog/Catalog.API/GlobalUsings.cs b/src/Services/Catalog/Catalog.API/GlobalUsings.cs new file mode 100644 index 000000000..48641cc80 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/GlobalUsings.cs @@ -0,0 +1,63 @@ +global using Azure.Core; +global using Azure.Identity; +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Extensions; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.ActionResults; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.Exceptions; +global using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents; +global using Grpc.Core; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Mvc.Filters; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore.Server.Kestrel.Core; +global using Microsoft.AspNetCore; +global using Microsoft.Extensions.Logging; +global using Microsoft.EntityFrameworkCore.Design; +global using Microsoft.EntityFrameworkCore.Metadata.Builders; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations; +global using Microsoft.eShopOnContainers.Services.Catalog.API; +global using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Model; +global using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Grpc; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Options; +global using Polly.Retry; +global using Polly; +global using Serilog.Context; +global using Serilog; +global using System.Collections.Generic; +global using System.Data.Common; +global using System.Data.SqlClient; +global using System.Globalization; +global using System.IO.Compression; +global using System.IO; +global using System.Linq; +global using System.Net; +global using System.Text.RegularExpressions; +global using System.Threading.Tasks; +global using System; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.Filters; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Azure.Messaging.ServiceBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +global using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.OpenApi.Models; +global using RabbitMQ.Client; +global using System.Reflection; \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Grpc/CatalogService.cs b/src/Services/Catalog/Catalog.API/Grpc/CatalogService.cs index 91270b576..ebd785462 100644 --- a/src/Services/Catalog/Catalog.API/Grpc/CatalogService.cs +++ b/src/Services/Catalog/Catalog.API/Grpc/CatalogService.cs @@ -1,188 +1,177 @@ using CatalogApi; -using Grpc.Core; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Catalog.API; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Catalog.API.Model; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using static CatalogApi.Catalog; -namespace Catalog.API.Grpc +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Grpc; +using Microsoft.Extensions.Logging; + +public class CatalogService : CatalogBase { - public class CatalogService : CatalogBase + private readonly CatalogContext _catalogContext; + private readonly CatalogSettings _settings; + private readonly ILogger _logger; + + public CatalogService(CatalogContext dbContext, IOptions settings, ILogger logger) { - private readonly CatalogContext _catalogContext; - private readonly CatalogSettings _settings; - private readonly ILogger _logger; + _settings = settings.Value; + _catalogContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); + _logger = logger; + } - public CatalogService(CatalogContext dbContext, IOptions settings, ILogger logger) + public override async Task GetItemById(CatalogItemRequest request, ServerCallContext context) + { + _logger.LogInformation("Begin grpc call CatalogService.GetItemById for product id {Id}", request.Id); + if (request.Id <= 0) { - _settings = settings.Value; - _catalogContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); - _logger = logger; + context.Status = new Status(StatusCode.FailedPrecondition, $"Id must be > 0 (received {request.Id})"); + return null; } - public override async Task GetItemById(CatalogItemRequest request, ServerCallContext context) - { - _logger.LogInformation("Begin grpc call CatalogService.GetItemById for product id {Id}", request.Id); - if (request.Id <= 0) - { - context.Status = new Status(StatusCode.FailedPrecondition, $"Id must be > 0 (received {request.Id})"); - return null; - } + var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(ci => ci.Id == request.Id); + var baseUri = _settings.PicBaseUrl; + var azureStorageEnabled = _settings.AzureStorageEnabled; + item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); - var item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(ci => ci.Id == request.Id); - var baseUri = _settings.PicBaseUrl; - var azureStorageEnabled = _settings.AzureStorageEnabled; - item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); - - if (item != null) + if (item != null) + { + return new CatalogItemResponse() { - return new CatalogItemResponse() - { - AvailableStock = item.AvailableStock, - Description = item.Description, - Id = item.Id, - MaxStockThreshold = item.MaxStockThreshold, - Name = item.Name, - OnReorder = item.OnReorder, - PictureFileName = item.PictureFileName, - PictureUri = item.PictureUri, - Price = (double)item.Price, - RestockThreshold = item.RestockThreshold - }; - } - - context.Status = new Status(StatusCode.NotFound, $"Product with id {request.Id} do not exist"); - return null; + AvailableStock = item.AvailableStock, + Description = item.Description, + Id = item.Id, + MaxStockThreshold = item.MaxStockThreshold, + Name = item.Name, + OnReorder = item.OnReorder, + PictureFileName = item.PictureFileName, + PictureUri = item.PictureUri, + Price = (double)item.Price, + RestockThreshold = item.RestockThreshold + }; } - public override async Task GetItemsByIds(CatalogItemsRequest request, ServerCallContext context) + context.Status = new Status(StatusCode.NotFound, $"Product with id {request.Id} do not exist"); + return null; + } + + public override async Task GetItemsByIds(CatalogItemsRequest request, ServerCallContext context) + { + if (!string.IsNullOrEmpty(request.Ids)) { - if (!string.IsNullOrEmpty(request.Ids)) - { - var items = await GetItemsByIdsAsync(request.Ids); + var items = await GetItemsByIdsAsync(request.Ids); - context.Status = !items.Any() ? - new Status(StatusCode.NotFound, $"ids value invalid. Must be comma-separated list of numbers") : - new Status(StatusCode.OK, string.Empty); + context.Status = !items.Any() ? + new Status(StatusCode.NotFound, $"ids value invalid. Must be comma-separated list of numbers") : + new Status(StatusCode.OK, string.Empty); - return this.MapToResponse(items); - } + return this.MapToResponse(items); + } - var totalItems = await _catalogContext.CatalogItems - .LongCountAsync(); + var totalItems = await _catalogContext.CatalogItems + .LongCountAsync(); - var itemsOnPage = await _catalogContext.CatalogItems - .OrderBy(c => c.Name) - .Skip(request.PageSize * request.PageIndex) - .Take(request.PageSize) - .ToListAsync(); + var itemsOnPage = await _catalogContext.CatalogItems + .OrderBy(c => c.Name) + .Skip(request.PageSize * request.PageIndex) + .Take(request.PageSize) + .ToListAsync(); - /* The "awesome" fix for testing Devspaces */ + /* The "awesome" fix for testing Devspaces */ - /* - foreach (var pr in itemsOnPage) { - pr.Name = "Awesome " + pr.Name; - } + /* + foreach (var pr in itemsOnPage) { + pr.Name = "Awesome " + pr.Name; + } - */ + */ - itemsOnPage = ChangeUriPlaceholder(itemsOnPage); + itemsOnPage = ChangeUriPlaceholder(itemsOnPage); - var model = this.MapToResponse(itemsOnPage, totalItems, request.PageIndex, request.PageSize); - context.Status = new Status(StatusCode.OK, string.Empty); + var model = this.MapToResponse(itemsOnPage, totalItems, request.PageIndex, request.PageSize); + context.Status = new Status(StatusCode.OK, string.Empty); - return model; - } + return model; + } - private PaginatedItemsResponse MapToResponse(List items) - { - return this.MapToResponse(items, items.Count, 1, items.Count); - } + private PaginatedItemsResponse MapToResponse(List items) + { + return this.MapToResponse(items, items.Count, 1, items.Count); + } - private PaginatedItemsResponse MapToResponse(List items, long count, int pageIndex, int pageSize) + private PaginatedItemsResponse MapToResponse(List items, long count, int pageIndex, int pageSize) + { + var result = new PaginatedItemsResponse() { - var result = new PaginatedItemsResponse() - { - Count = count, - PageIndex = pageIndex, - PageSize = pageSize, - }; + Count = count, + PageIndex = pageIndex, + PageSize = pageSize, + }; - items.ForEach(i => + items.ForEach(i => + { + var brand = i.CatalogBrand == null + ? null + : new CatalogApi.CatalogBrand() + { + Id = i.CatalogBrand.Id, + Name = i.CatalogBrand.Brand, + }; + var catalogType = i.CatalogType == null + ? null + : new CatalogApi.CatalogType() + { + Id = i.CatalogType.Id, + Type = i.CatalogType.Type, + }; + + result.Data.Add(new CatalogItemResponse() { - var brand = i.CatalogBrand == null - ? null - : new CatalogApi.CatalogBrand() - { - Id = i.CatalogBrand.Id, - Name = i.CatalogBrand.Brand, - }; - var catalogType = i.CatalogType == null - ? null - : new CatalogApi.CatalogType() - { - Id = i.CatalogType.Id, - Type = i.CatalogType.Type, - }; - - result.Data.Add(new CatalogItemResponse() - { - AvailableStock = i.AvailableStock, - Description = i.Description, - Id = i.Id, - MaxStockThreshold = i.MaxStockThreshold, - Name = i.Name, - OnReorder = i.OnReorder, - PictureFileName = i.PictureFileName, - PictureUri = i.PictureUri, - RestockThreshold = i.RestockThreshold, - CatalogBrand = brand, - CatalogType = catalogType, - Price = (double)i.Price, - }); + AvailableStock = i.AvailableStock, + Description = i.Description, + Id = i.Id, + MaxStockThreshold = i.MaxStockThreshold, + Name = i.Name, + OnReorder = i.OnReorder, + PictureFileName = i.PictureFileName, + PictureUri = i.PictureUri, + RestockThreshold = i.RestockThreshold, + CatalogBrand = brand, + CatalogType = catalogType, + Price = (double)i.Price, }); + }); - return result; - } + return result; + } - private async Task> GetItemsByIdsAsync(string ids) + private async Task> GetItemsByIdsAsync(string ids) + { + var numIds = ids.Split(',').Select(id => (Ok: int.TryParse(id, out int x), Value: x)); + + if (!numIds.All(nid => nid.Ok)) { - var numIds = ids.Split(',').Select(id => (Ok: int.TryParse(id, out int x), Value: x)); + return new List(); + } - if (!numIds.All(nid => nid.Ok)) - { - return new List(); - } + var idsToSelect = numIds + .Select(id => id.Value); - var idsToSelect = numIds - .Select(id => id.Value); + var items = await _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToListAsync(); - var items = await _catalogContext.CatalogItems.Where(ci => idsToSelect.Contains(ci.Id)).ToListAsync(); + items = ChangeUriPlaceholder(items); - items = ChangeUriPlaceholder(items); + return items; + } - return items; - } + private List ChangeUriPlaceholder(List items) + { + var baseUri = _settings.PicBaseUrl; + var azureStorageEnabled = _settings.AzureStorageEnabled; - private List ChangeUriPlaceholder(List items) + foreach (var item in items) { - var baseUri = _settings.PicBaseUrl; - var azureStorageEnabled = _settings.AzureStorageEnabled; - - foreach (var item in items) - { - item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); - } - - return items; + item.FillProductUrl(baseUri, azureStorageEnabled: azureStorageEnabled); } + + return items; } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs index a6138b476..53af0f0b8 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs @@ -1,14 +1,10 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.ActionResults; -namespace Catalog.API.Infrastructure.ActionResults +public class InternalServerErrorObjectResult : ObjectResult { - public class InternalServerErrorObjectResult : ObjectResult + public InternalServerErrorObjectResult(object error) + : base(error) { - public InternalServerErrorObjectResult(object error) - : base(error) - { - StatusCode = StatusCodes.Status500InternalServerError; - } + StatusCode = StatusCodes.Status500InternalServerError; } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs index ee440c1ef..cf152f40f 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContext.cs @@ -1,36 +1,32 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure -{ - using EntityConfigurations; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Design; - using Model; +using Microsoft.eShopOnContainers.Services.Catalog.API.Model; + +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; - public class CatalogContext : DbContext +public class CatalogContext : DbContext +{ + public CatalogContext(DbContextOptions options) : base(options) { - public CatalogContext(DbContextOptions options) : base(options) - { - } - public DbSet CatalogItems { get; set; } - public DbSet CatalogBrands { get; set; } - public DbSet CatalogTypes { get; set; } + } + public DbSet CatalogItems { get; set; } + public DbSet CatalogBrands { get; set; } + public DbSet CatalogTypes { get; set; } - protected override void OnModelCreating(ModelBuilder builder) - { - builder.ApplyConfiguration(new CatalogBrandEntityTypeConfiguration()); - builder.ApplyConfiguration(new CatalogTypeEntityTypeConfiguration()); - builder.ApplyConfiguration(new CatalogItemEntityTypeConfiguration()); - } + protected override void OnModelCreating(ModelBuilder builder) + { + builder.ApplyConfiguration(new CatalogBrandEntityTypeConfiguration()); + builder.ApplyConfiguration(new CatalogTypeEntityTypeConfiguration()); + builder.ApplyConfiguration(new CatalogItemEntityTypeConfiguration()); } +} - public class CatalogContextDesignFactory : IDesignTimeDbContextFactory +public class CatalogContextDesignFactory : IDesignTimeDbContextFactory +{ + public CatalogContext CreateDbContext(string[] args) { - public CatalogContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder() - .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;Integrated Security=true"); + var optionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;Integrated Security=true"); - return new CatalogContext(optionsBuilder.Options); - } + return new CatalogContext(optionsBuilder.Options); } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs index 5416b377a..4e3a0f6e0 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs @@ -1,386 +1,370 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure +using Microsoft.eShopOnContainers.Services.Catalog.API.Model; + +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; + +public class CatalogContextSeed { - using Extensions.Logging; - using global::Catalog.API.Extensions; - using Microsoft.AspNetCore.Hosting; - using Microsoft.Extensions.Options; - using Model; - using Polly; - using Polly.Retry; - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - using System.Globalization; - using System.IO; - using System.IO.Compression; - using System.Linq; - using System.Text.RegularExpressions; - using System.Threading.Tasks; - - public class CatalogContextSeed + public async Task SeedAsync(CatalogContext context, IWebHostEnvironment env, IOptions settings, ILogger logger) { - public async Task SeedAsync(CatalogContext context, IWebHostEnvironment env, IOptions settings, ILogger logger) + var policy = CreatePolicy(logger, nameof(CatalogContextSeed)); + + await policy.ExecuteAsync(async () => { - var policy = CreatePolicy(logger, nameof(CatalogContextSeed)); + var useCustomizationData = settings.Value.UseCustomizationData; + var contentRootPath = env.ContentRootPath; + var picturePath = env.WebRootPath; - await policy.ExecuteAsync(async () => + if (!context.CatalogBrands.Any()) { - var useCustomizationData = settings.Value.UseCustomizationData; - var contentRootPath = env.ContentRootPath; - var picturePath = env.WebRootPath; + await context.CatalogBrands.AddRangeAsync(useCustomizationData + ? GetCatalogBrandsFromFile(contentRootPath, logger) + : GetPreconfiguredCatalogBrands()); - if (!context.CatalogBrands.Any()) - { - await context.CatalogBrands.AddRangeAsync(useCustomizationData - ? GetCatalogBrandsFromFile(contentRootPath, logger) - : GetPreconfiguredCatalogBrands()); + await context.SaveChangesAsync(); + } - await context.SaveChangesAsync(); - } + if (!context.CatalogTypes.Any()) + { + await context.CatalogTypes.AddRangeAsync(useCustomizationData + ? GetCatalogTypesFromFile(contentRootPath, logger) + : GetPreconfiguredCatalogTypes()); - if (!context.CatalogTypes.Any()) - { - await context.CatalogTypes.AddRangeAsync(useCustomizationData - ? GetCatalogTypesFromFile(contentRootPath, logger) - : GetPreconfiguredCatalogTypes()); + await context.SaveChangesAsync(); + } - await context.SaveChangesAsync(); - } + if (!context.CatalogItems.Any()) + { + await context.CatalogItems.AddRangeAsync(useCustomizationData + ? GetCatalogItemsFromFile(contentRootPath, context, logger) + : GetPreconfiguredItems()); - if (!context.CatalogItems.Any()) - { - await context.CatalogItems.AddRangeAsync(useCustomizationData - ? GetCatalogItemsFromFile(contentRootPath, context, logger) - : GetPreconfiguredItems()); + await context.SaveChangesAsync(); - await context.SaveChangesAsync(); + GetCatalogItemPictures(contentRootPath, picturePath); + } + }); + } - GetCatalogItemPictures(contentRootPath, picturePath); - } - }); + private IEnumerable GetCatalogBrandsFromFile(string contentRootPath, ILogger logger) + { + string csvFileCatalogBrands = Path.Combine(contentRootPath, "Setup", "CatalogBrands.csv"); + + if (!File.Exists(csvFileCatalogBrands)) + { + return GetPreconfiguredCatalogBrands(); } - private IEnumerable GetCatalogBrandsFromFile(string contentRootPath, ILogger logger) + string[] csvheaders; + try { - string csvFileCatalogBrands = Path.Combine(contentRootPath, "Setup", "CatalogBrands.csv"); + string[] requiredHeaders = { "catalogbrand" }; + csvheaders = GetHeaders(csvFileCatalogBrands, requiredHeaders); + } + catch (Exception ex) + { + logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); + return GetPreconfiguredCatalogBrands(); + } - if (!File.Exists(csvFileCatalogBrands)) - { - return GetPreconfiguredCatalogBrands(); - } + return File.ReadAllLines(csvFileCatalogBrands) + .Skip(1) // skip header row + .SelectTry(x => CreateCatalogBrand(x)) + .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) + .Where(x => x != null); + } - string[] csvheaders; - try - { - string[] requiredHeaders = { "catalogbrand" }; - csvheaders = GetHeaders(csvFileCatalogBrands, requiredHeaders); - } - catch (Exception ex) - { - logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); - return GetPreconfiguredCatalogBrands(); - } + private CatalogBrand CreateCatalogBrand(string brand) + { + brand = brand.Trim('"').Trim(); - return File.ReadAllLines(csvFileCatalogBrands) - .Skip(1) // skip header row - .SelectTry(x => CreateCatalogBrand(x)) - .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) - .Where(x => x != null); + if (String.IsNullOrEmpty(brand)) + { + throw new Exception("catalog Brand Name is empty"); } - private CatalogBrand CreateCatalogBrand(string brand) + return new CatalogBrand { - brand = brand.Trim('"').Trim(); + Brand = brand, + }; + } - if (String.IsNullOrEmpty(brand)) - { - throw new Exception("catalog Brand Name is empty"); - } + private IEnumerable GetPreconfiguredCatalogBrands() + { + return new List() + { + new() { Brand = "Azure"}, + new() { Brand = ".NET" }, + new() { Brand = "Visual Studio" }, + new() { Brand = "SQL Server" }, + new() { Brand = "Other" } + }; + } - return new CatalogBrand - { - Brand = brand, - }; - } + private IEnumerable GetCatalogTypesFromFile(string contentRootPath, ILogger logger) + { + string csvFileCatalogTypes = Path.Combine(contentRootPath, "Setup", "CatalogTypes.csv"); - private IEnumerable GetPreconfiguredCatalogBrands() + if (!File.Exists(csvFileCatalogTypes)) { - return new List() - { - new CatalogBrand() { Brand = "Azure"}, - new CatalogBrand() { Brand = ".NET" }, - new CatalogBrand() { Brand = "Visual Studio" }, - new CatalogBrand() { Brand = "SQL Server" }, - new CatalogBrand() { Brand = "Other" } - }; + return GetPreconfiguredCatalogTypes(); } - private IEnumerable GetCatalogTypesFromFile(string contentRootPath, ILogger logger) + string[] csvheaders; + try { - string csvFileCatalogTypes = Path.Combine(contentRootPath, "Setup", "CatalogTypes.csv"); + string[] requiredHeaders = { "catalogtype" }; + csvheaders = GetHeaders(csvFileCatalogTypes, requiredHeaders); + } + catch (Exception ex) + { + logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); + return GetPreconfiguredCatalogTypes(); + } - if (!File.Exists(csvFileCatalogTypes)) - { - return GetPreconfiguredCatalogTypes(); - } + return File.ReadAllLines(csvFileCatalogTypes) + .Skip(1) // skip header row + .SelectTry(x => CreateCatalogType(x)) + .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) + .Where(x => x != null); + } - string[] csvheaders; - try - { - string[] requiredHeaders = { "catalogtype" }; - csvheaders = GetHeaders(csvFileCatalogTypes, requiredHeaders); - } - catch (Exception ex) - { - logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); - return GetPreconfiguredCatalogTypes(); - } + private CatalogType CreateCatalogType(string type) + { + type = type.Trim('"').Trim(); - return File.ReadAllLines(csvFileCatalogTypes) - .Skip(1) // skip header row - .SelectTry(x => CreateCatalogType(x)) - .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) - .Where(x => x != null); + if (String.IsNullOrEmpty(type)) + { + throw new Exception("catalog Type Name is empty"); } - private CatalogType CreateCatalogType(string type) + return new CatalogType { - type = type.Trim('"').Trim(); + Type = type, + }; + } - if (String.IsNullOrEmpty(type)) - { - throw new Exception("catalog Type Name is empty"); - } + private IEnumerable GetPreconfiguredCatalogTypes() + { + return new List() + { + new() { Type = "Mug"}, + new() { Type = "T-Shirt" }, + new() { Type = "Sheet" }, + new() { Type = "USB Memory Stick" } + }; + } - return new CatalogType - { - Type = type, - }; - } + private IEnumerable GetCatalogItemsFromFile(string contentRootPath, CatalogContext context, ILogger logger) + { + string csvFileCatalogItems = Path.Combine(contentRootPath, "Setup", "CatalogItems.csv"); - private IEnumerable GetPreconfiguredCatalogTypes() + if (!File.Exists(csvFileCatalogItems)) { - return new List() - { - new CatalogType() { Type = "Mug"}, - new CatalogType() { Type = "T-Shirt" }, - new CatalogType() { Type = "Sheet" }, - new CatalogType() { Type = "USB Memory Stick" } - }; + return GetPreconfiguredItems(); } - private IEnumerable GetCatalogItemsFromFile(string contentRootPath, CatalogContext context, ILogger logger) + string[] csvheaders; + try { - string csvFileCatalogItems = Path.Combine(contentRootPath, "Setup", "CatalogItems.csv"); - - if (!File.Exists(csvFileCatalogItems)) - { - return GetPreconfiguredItems(); - } + string[] requiredHeaders = { "catalogtypename", "catalogbrandname", "description", "name", "price", "picturefilename" }; + string[] optionalheaders = { "availablestock", "restockthreshold", "maxstockthreshold", "onreorder" }; + csvheaders = GetHeaders(csvFileCatalogItems, requiredHeaders, optionalheaders); + } + catch (Exception ex) + { + logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); + return GetPreconfiguredItems(); + } - string[] csvheaders; - try - { - string[] requiredHeaders = { "catalogtypename", "catalogbrandname", "description", "name", "price", "picturefilename" }; - string[] optionalheaders = { "availablestock", "restockthreshold", "maxstockthreshold", "onreorder" }; - csvheaders = GetHeaders(csvFileCatalogItems, requiredHeaders, optionalheaders); - } - catch (Exception ex) - { - logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); - return GetPreconfiguredItems(); - } + var catalogTypeIdLookup = context.CatalogTypes.ToDictionary(ct => ct.Type, ct => ct.Id); + var catalogBrandIdLookup = context.CatalogBrands.ToDictionary(ct => ct.Brand, ct => ct.Id); - var catalogTypeIdLookup = context.CatalogTypes.ToDictionary(ct => ct.Type, ct => ct.Id); - var catalogBrandIdLookup = context.CatalogBrands.ToDictionary(ct => ct.Brand, ct => ct.Id); + return File.ReadAllLines(csvFileCatalogItems) + .Skip(1) // skip header row + .Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)")) + .SelectTry(column => CreateCatalogItem(column, csvheaders, catalogTypeIdLookup, catalogBrandIdLookup)) + .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) + .Where(x => x != null); + } - return File.ReadAllLines(csvFileCatalogItems) - .Skip(1) // skip header row - .Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)")) - .SelectTry(column => CreateCatalogItem(column, csvheaders, catalogTypeIdLookup, catalogBrandIdLookup)) - .OnCaughtException(ex => { logger.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) - .Where(x => x != null); + private CatalogItem CreateCatalogItem(string[] column, string[] headers, Dictionary catalogTypeIdLookup, Dictionary catalogBrandIdLookup) + { + if (column.Count() != headers.Count()) + { + throw new Exception($"column count '{column.Count()}' not the same as headers count'{headers.Count()}'"); } - private CatalogItem CreateCatalogItem(string[] column, string[] headers, Dictionary catalogTypeIdLookup, Dictionary catalogBrandIdLookup) + string catalogTypeName = column[Array.IndexOf(headers, "catalogtypename")].Trim('"').Trim(); + if (!catalogTypeIdLookup.ContainsKey(catalogTypeName)) { - if (column.Count() != headers.Count()) - { - throw new Exception($"column count '{column.Count()}' not the same as headers count'{headers.Count()}'"); - } - - string catalogTypeName = column[Array.IndexOf(headers, "catalogtypename")].Trim('"').Trim(); - if (!catalogTypeIdLookup.ContainsKey(catalogTypeName)) - { - throw new Exception($"type={catalogTypeName} does not exist in catalogTypes"); - } + throw new Exception($"type={catalogTypeName} does not exist in catalogTypes"); + } - string catalogBrandName = column[Array.IndexOf(headers, "catalogbrandname")].Trim('"').Trim(); - if (!catalogBrandIdLookup.ContainsKey(catalogBrandName)) - { - throw new Exception($"type={catalogTypeName} does not exist in catalogTypes"); - } + string catalogBrandName = column[Array.IndexOf(headers, "catalogbrandname")].Trim('"').Trim(); + if (!catalogBrandIdLookup.ContainsKey(catalogBrandName)) + { + throw new Exception($"type={catalogBrandName} does not exist in catalogTypes"); + } - string priceString = column[Array.IndexOf(headers, "price")].Trim('"').Trim(); - if (!Decimal.TryParse(priceString, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out Decimal price)) - { - throw new Exception($"price={priceString}is not a valid decimal number"); - } + string priceString = column[Array.IndexOf(headers, "price")].Trim('"').Trim(); + if (!Decimal.TryParse(priceString, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out Decimal price)) + { + throw new Exception($"price={priceString}is not a valid decimal number"); + } - var catalogItem = new CatalogItem() - { - CatalogTypeId = catalogTypeIdLookup[catalogTypeName], - CatalogBrandId = catalogBrandIdLookup[catalogBrandName], - Description = column[Array.IndexOf(headers, "description")].Trim('"').Trim(), - Name = column[Array.IndexOf(headers, "name")].Trim('"').Trim(), - Price = price, - PictureFileName = column[Array.IndexOf(headers, "picturefilename")].Trim('"').Trim(), - }; - - int availableStockIndex = Array.IndexOf(headers, "availablestock"); - if (availableStockIndex != -1) + var catalogItem = new CatalogItem() + { + CatalogTypeId = catalogTypeIdLookup[catalogTypeName], + CatalogBrandId = catalogBrandIdLookup[catalogBrandName], + Description = column[Array.IndexOf(headers, "description")].Trim('"').Trim(), + Name = column[Array.IndexOf(headers, "name")].Trim('"').Trim(), + Price = price, + PictureFileName = column[Array.IndexOf(headers, "picturefilename")].Trim('"').Trim(), + }; + + int availableStockIndex = Array.IndexOf(headers, "availablestock"); + if (availableStockIndex != -1) + { + string availableStockString = column[availableStockIndex].Trim('"').Trim(); + if (!String.IsNullOrEmpty(availableStockString)) { - string availableStockString = column[availableStockIndex].Trim('"').Trim(); - if (!String.IsNullOrEmpty(availableStockString)) + if (int.TryParse(availableStockString, out int availableStock)) { - if (int.TryParse(availableStockString, out int availableStock)) - { - catalogItem.AvailableStock = availableStock; - } - else - { - throw new Exception($"availableStock={availableStockString} is not a valid integer"); - } + catalogItem.AvailableStock = availableStock; + } + else + { + throw new Exception($"availableStock={availableStockString} is not a valid integer"); } } + } - int restockThresholdIndex = Array.IndexOf(headers, "restockthreshold"); - if (restockThresholdIndex != -1) + int restockThresholdIndex = Array.IndexOf(headers, "restockthreshold"); + if (restockThresholdIndex != -1) + { + string restockThresholdString = column[restockThresholdIndex].Trim('"').Trim(); + if (!String.IsNullOrEmpty(restockThresholdString)) { - string restockThresholdString = column[restockThresholdIndex].Trim('"').Trim(); - if (!String.IsNullOrEmpty(restockThresholdString)) + if (int.TryParse(restockThresholdString, out int restockThreshold)) { - if (int.TryParse(restockThresholdString, out int restockThreshold)) - { - catalogItem.RestockThreshold = restockThreshold; - } - else - { - throw new Exception($"restockThreshold={restockThreshold} is not a valid integer"); - } + catalogItem.RestockThreshold = restockThreshold; + } + else + { + throw new Exception($"restockThreshold={restockThreshold} is not a valid integer"); } } + } - int maxStockThresholdIndex = Array.IndexOf(headers, "maxstockthreshold"); - if (maxStockThresholdIndex != -1) + int maxStockThresholdIndex = Array.IndexOf(headers, "maxstockthreshold"); + if (maxStockThresholdIndex != -1) + { + string maxStockThresholdString = column[maxStockThresholdIndex].Trim('"').Trim(); + if (!String.IsNullOrEmpty(maxStockThresholdString)) { - string maxStockThresholdString = column[maxStockThresholdIndex].Trim('"').Trim(); - if (!String.IsNullOrEmpty(maxStockThresholdString)) + if (int.TryParse(maxStockThresholdString, out int maxStockThreshold)) { - if (int.TryParse(maxStockThresholdString, out int maxStockThreshold)) - { - catalogItem.MaxStockThreshold = maxStockThreshold; - } - else - { - throw new Exception($"maxStockThreshold={maxStockThreshold} is not a valid integer"); - } + catalogItem.MaxStockThreshold = maxStockThreshold; + } + else + { + throw new Exception($"maxStockThreshold={maxStockThreshold} is not a valid integer"); } } + } - int onReorderIndex = Array.IndexOf(headers, "onreorder"); - if (onReorderIndex != -1) + int onReorderIndex = Array.IndexOf(headers, "onreorder"); + if (onReorderIndex != -1) + { + string onReorderString = column[onReorderIndex].Trim('"').Trim(); + if (!String.IsNullOrEmpty(onReorderString)) { - string onReorderString = column[onReorderIndex].Trim('"').Trim(); - if (!String.IsNullOrEmpty(onReorderString)) + if (bool.TryParse(onReorderString, out bool onReorder)) { - if (bool.TryParse(onReorderString, out bool onReorder)) - { - catalogItem.OnReorder = onReorder; - } - else - { - throw new Exception($"onReorder={onReorderString} is not a valid boolean"); - } + catalogItem.OnReorder = onReorder; + } + else + { + throw new Exception($"onReorder={onReorderString} is not a valid boolean"); } } - - return catalogItem; } - private IEnumerable GetPreconfiguredItems() + return catalogItem; + } + + private IEnumerable GetPreconfiguredItems() + { + return new List() { - return new List() - { - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureFileName = "1.png" }, - new CatalogItem { CatalogTypeId = 1, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureFileName = "2.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureFileName = "3.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureFileName = "4.png" }, - new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureFileName = "5.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureFileName = "6.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureFileName = "7.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureFileName = "8.png" }, - new CatalogItem { CatalogTypeId = 1, CatalogBrandId = 5, AvailableStock = 100, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureFileName = "9.png" }, - new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureFileName = "10.png" }, - new CatalogItem { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureFileName = "11.png" }, - new CatalogItem { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" }, - }; - } + new() { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Bot Black Hoodie", Name = ".NET Bot Black Hoodie", Price = 19.5M, PictureFileName = "1.png" }, + new() { CatalogTypeId = 1, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Black & White Mug", Name = ".NET Black & White Mug", Price= 8.50M, PictureFileName = "2.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White T-Shirt", Name = "Prism White T-Shirt", Price = 12, PictureFileName = "3.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation T-shirt", Name = ".NET Foundation T-shirt", Price = 12, PictureFileName = "4.png" }, + new() { CatalogTypeId = 3, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red Sheet", Name = "Roslyn Red Sheet", Price = 8.5M, PictureFileName = "5.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Blue Hoodie", Name = ".NET Blue Hoodie", Price = 12, PictureFileName = "6.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Roslyn Red T-Shirt", Name = "Roslyn Red T-Shirt", Price = 12, PictureFileName = "7.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Kudu Purple Hoodie", Name = "Kudu Purple Hoodie", Price = 8.5M, PictureFileName = "8.png" }, + new() { CatalogTypeId = 1, CatalogBrandId = 5, AvailableStock = 100, Description = "Cup White Mug", Name = "Cup White Mug", Price = 12, PictureFileName = "9.png" }, + new() { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = ".NET Foundation Sheet", Name = ".NET Foundation Sheet", Price = 12, PictureFileName = "10.png" }, + new() { CatalogTypeId = 3, CatalogBrandId = 2, AvailableStock = 100, Description = "Cup Sheet", Name = "Cup Sheet", Price = 8.5M, PictureFileName = "11.png" }, + new() { CatalogTypeId = 2, CatalogBrandId = 5, AvailableStock = 100, Description = "Prism White TShirt", Name = "Prism White TShirt", Price = 12, PictureFileName = "12.png" }, + }; + } - private string[] GetHeaders(string csvfile, string[] requiredHeaders, string[] optionalHeaders = null) + private string[] GetHeaders(string csvfile, string[] requiredHeaders, string[] optionalHeaders = null) + { + string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(','); + + if (csvheaders.Count() < requiredHeaders.Count()) { - string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(','); + throw new Exception($"requiredHeader count '{ requiredHeaders.Count()}' is bigger then csv header count '{csvheaders.Count()}' "); + } - if (csvheaders.Count() < requiredHeaders.Count()) + if (optionalHeaders != null) + { + if (csvheaders.Count() > (requiredHeaders.Count() + optionalHeaders.Count())) { - throw new Exception($"requiredHeader count '{ requiredHeaders.Count()}' is bigger then csv header count '{csvheaders.Count()}' "); + throw new Exception($"csv header count '{csvheaders.Count()}' is larger then required '{requiredHeaders.Count()}' and optional '{optionalHeaders.Count()}' headers count"); } + } - if (optionalHeaders != null) + foreach (var requiredHeader in requiredHeaders) + { + if (!csvheaders.Contains(requiredHeader)) { - if (csvheaders.Count() > (requiredHeaders.Count() + optionalHeaders.Count())) - { - throw new Exception($"csv header count '{csvheaders.Count()}' is larger then required '{requiredHeaders.Count()}' and optional '{optionalHeaders.Count()}' headers count"); - } + throw new Exception($"does not contain required header '{requiredHeader}'"); } + } + + return csvheaders; + } - foreach (var requiredHeader in requiredHeaders) + private void GetCatalogItemPictures(string contentRootPath, string picturePath) + { + if (picturePath != null) + { + DirectoryInfo directory = new DirectoryInfo(picturePath); + foreach (FileInfo file in directory.GetFiles()) { - if (!csvheaders.Contains(requiredHeader)) - { - throw new Exception($"does not contain required header '{requiredHeader}'"); - } + file.Delete(); } - return csvheaders; + string zipFileCatalogItemPictures = Path.Combine(contentRootPath, "Setup", "CatalogItems.zip"); + ZipFile.ExtractToDirectory(zipFileCatalogItemPictures, picturePath); } + } - private void GetCatalogItemPictures(string contentRootPath, string picturePath) - { - if (picturePath != null) - { - DirectoryInfo directory = new DirectoryInfo(picturePath); - foreach (FileInfo file in directory.GetFiles()) + private AsyncRetryPolicy CreatePolicy(ILogger logger, string prefix, int retries = 3) + { + return Policy.Handle(). + WaitAndRetryAsync( + retryCount: retries, + sleepDurationProvider: retry => TimeSpan.FromSeconds(5), + onRetry: (exception, timeSpan, retry, ctx) => { - file.Delete(); + logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries); } - - string zipFileCatalogItemPictures = Path.Combine(contentRootPath, "Setup", "CatalogItems.zip"); - ZipFile.ExtractToDirectory(zipFileCatalogItemPictures, picturePath); - } - } - - private AsyncRetryPolicy CreatePolicy(ILogger logger, string prefix, int retries = 3) - { - return Policy.Handle(). - WaitAndRetryAsync( - retryCount: retries, - sleepDurationProvider: retry => TimeSpan.FromSeconds(5), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries); - } - ); - } + ); } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs b/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs index 35d307ee3..1263891ad 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogBrandEntityTypeConfiguration.cs @@ -1,25 +1,20 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Catalog.API.Model; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations; -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations +class CatalogBrandEntityTypeConfiguration + : IEntityTypeConfiguration { - class CatalogBrandEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("CatalogBrand"); + builder.ToTable("CatalogBrand"); - builder.HasKey(ci => ci.Id); + builder.HasKey(ci => ci.Id); - builder.Property(ci => ci.Id) - .UseHiLo("catalog_brand_hilo") - .IsRequired(); + builder.Property(ci => ci.Id) + .UseHiLo("catalog_brand_hilo") + .IsRequired(); - builder.Property(cb => cb.Brand) - .IsRequired() - .HasMaxLength(100); - } + builder.Property(cb => cb.Brand) + .IsRequired() + .HasMaxLength(100); } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs b/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs index 33079099c..d7cc8b2d5 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogItemEntityTypeConfiguration.cs @@ -1,39 +1,34 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Catalog.API.Model; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations; -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations +class CatalogItemEntityTypeConfiguration + : IEntityTypeConfiguration { - class CatalogItemEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Catalog"); + builder.ToTable("Catalog"); - builder.Property(ci => ci.Id) - .UseHiLo("catalog_hilo") - .IsRequired(); + builder.Property(ci => ci.Id) + .UseHiLo("catalog_hilo") + .IsRequired(); - builder.Property(ci => ci.Name) - .IsRequired(true) - .HasMaxLength(50); + builder.Property(ci => ci.Name) + .IsRequired(true) + .HasMaxLength(50); - builder.Property(ci => ci.Price) - .IsRequired(true); + builder.Property(ci => ci.Price) + .IsRequired(true); - builder.Property(ci => ci.PictureFileName) - .IsRequired(false); + builder.Property(ci => ci.PictureFileName) + .IsRequired(false); - builder.Ignore(ci => ci.PictureUri); + builder.Ignore(ci => ci.PictureUri); - builder.HasOne(ci => ci.CatalogBrand) - .WithMany() - .HasForeignKey(ci => ci.CatalogBrandId); + builder.HasOne(ci => ci.CatalogBrand) + .WithMany() + .HasForeignKey(ci => ci.CatalogBrandId); - builder.HasOne(ci => ci.CatalogType) - .WithMany() - .HasForeignKey(ci => ci.CatalogTypeId); - } + builder.HasOne(ci => ci.CatalogType) + .WithMany() + .HasForeignKey(ci => ci.CatalogTypeId); } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs b/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs index df42826c9..698de0d8f 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/EntityConfigurations/CatalogTypeEntityTypeConfiguration.cs @@ -1,25 +1,20 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Catalog.API.Model; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations; -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.EntityConfigurations +class CatalogTypeEntityTypeConfiguration + : IEntityTypeConfiguration { - class CatalogTypeEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder builder) { - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("CatalogType"); + builder.ToTable("CatalogType"); - builder.HasKey(ci => ci.Id); + builder.HasKey(ci => ci.Id); - builder.Property(ci => ci.Id) - .UseHiLo("catalog_type_hilo") - .IsRequired(); + builder.Property(ci => ci.Id) + .UseHiLo("catalog_type_hilo") + .IsRequired(); - builder.Property(cb => cb.Type) - .IsRequired() - .HasMaxLength(100); - } + builder.Property(cb => cb.Type) + .IsRequired() + .HasMaxLength(100); } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs b/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs index 45295994e..4bc8db208 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/Exceptions/CatalogDomainException.cs @@ -1,21 +1,18 @@ -using System; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.Exceptions; -namespace Catalog.API.Infrastructure.Exceptions +/// +/// Exception type for app exceptions +/// +public class CatalogDomainException : Exception { - /// - /// Exception type for app exceptions - /// - public class CatalogDomainException : Exception - { - public CatalogDomainException() - { } + public CatalogDomainException() + { } - public CatalogDomainException(string message) - : base(message) - { } + public CatalogDomainException(string message) + : base(message) + { } - public CatalogDomainException(string message, Exception innerException) - : base(message, innerException) - { } - } + public CatalogDomainException(string message, Exception innerException) + : base(message, innerException) + { } } diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs index 5ddb81d63..66ee35e7b 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs @@ -1,69 +1,58 @@ -using Catalog.API.Infrastructure.ActionResults; -using Catalog.API.Infrastructure.Exceptions; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System.Net; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure.Filters; -namespace Catalog.API.Infrastructure.Filters +public class HttpGlobalExceptionFilter : IExceptionFilter { - public class HttpGlobalExceptionFilter : IExceptionFilter + private readonly IWebHostEnvironment env; + private readonly ILogger logger; + + public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) { - private readonly IWebHostEnvironment env; - private readonly ILogger logger; + this.env = env; + this.logger = logger; + } - public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) - { - this.env = env; - this.logger = logger; - } + public void OnException(ExceptionContext context) + { + logger.LogError(new EventId(context.Exception.HResult), + context.Exception, + context.Exception.Message); - public void OnException(ExceptionContext context) + if (context.Exception.GetType() == typeof(CatalogDomainException)) { - logger.LogError(new EventId(context.Exception.HResult), - context.Exception, - context.Exception.Message); - - if (context.Exception.GetType() == typeof(CatalogDomainException)) + var problemDetails = new ValidationProblemDetails() { - var problemDetails = new ValidationProblemDetails() - { - Instance = context.HttpContext.Request.Path, - Status = StatusCodes.Status400BadRequest, - Detail = "Please refer to the errors property for additional details." - }; + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; - problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); + problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); - context.Result = new BadRequestObjectResult(problemDetails); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - else + context.Result = new BadRequestObjectResult(problemDetails); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + } + else + { + var json = new JsonErrorResponse { - var json = new JsonErrorResponse - { - Messages = new[] { "An error ocurred." } - }; - - if (env.IsDevelopment()) - { - json.DeveloperMessage = context.Exception; - } + Messages = new[] { "An error ocurred." } + }; - context.Result = new InternalServerErrorObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + if (env.IsDevelopment()) + { + json.DeveloperMessage = context.Exception; } - context.ExceptionHandled = true; + + context.Result = new InternalServerErrorObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } + context.ExceptionHandled = true; + } - private class JsonErrorResponse - { - public string[] Messages { get; set; } + private class JsonErrorResponse + { + public string[] Messages { get; set; } - public object DeveloperMessage { get; set; } - } + public object DeveloperMessage { get; set; } } } diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs index 1ed2783df..282bea5b3 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs @@ -1,86 +1,74 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.Extensions.Logging; -using System; -using System.Data.Common; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents; -namespace Catalog.API.IntegrationEvents +public class CatalogIntegrationEventService : ICatalogIntegrationEventService, IDisposable { - public class CatalogIntegrationEventService : ICatalogIntegrationEventService, IDisposable + private readonly Func _integrationEventLogServiceFactory; + private readonly IEventBus _eventBus; + private readonly CatalogContext _catalogContext; + private readonly IIntegrationEventLogService _eventLogService; + private readonly ILogger _logger; + private volatile bool disposedValue; + + public CatalogIntegrationEventService( + ILogger logger, + IEventBus eventBus, + CatalogContext catalogContext, + Func integrationEventLogServiceFactory) { - private readonly Func _integrationEventLogServiceFactory; - private readonly IEventBus _eventBus; - private readonly CatalogContext _catalogContext; - private readonly IIntegrationEventLogService _eventLogService; - private readonly ILogger _logger; - private volatile bool disposedValue; + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _catalogContext = catalogContext ?? throw new ArgumentNullException(nameof(catalogContext)); + _integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory)); + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); + _eventLogService = _integrationEventLogServiceFactory(_catalogContext.Database.GetDbConnection()); + } - public CatalogIntegrationEventService( - ILogger logger, - IEventBus eventBus, - CatalogContext catalogContext, - Func integrationEventLogServiceFactory) + public async Task PublishThroughEventBusAsync(IntegrationEvent evt) + { + try { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _catalogContext = catalogContext ?? throw new ArgumentNullException(nameof(catalogContext)); - _integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory)); - _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); - _eventLogService = _integrationEventLogServiceFactory(_catalogContext.Database.GetDbConnection()); - } + _logger.LogInformation("----- Publishing integration event: {IntegrationEventId_published} from {AppName} - ({@IntegrationEvent})", evt.Id, Program.AppName, evt); - public async Task PublishThroughEventBusAsync(IntegrationEvent evt) + await _eventLogService.MarkEventAsInProgressAsync(evt.Id); + _eventBus.Publish(evt); + await _eventLogService.MarkEventAsPublishedAsync(evt.Id); + } + catch (Exception ex) { - try - { - _logger.LogInformation("----- Publishing integration event: {IntegrationEventId_published} from {AppName} - ({@IntegrationEvent})", evt.Id, Program.AppName, evt); - - await _eventLogService.MarkEventAsInProgressAsync(evt.Id); - _eventBus.Publish(evt); - await _eventLogService.MarkEventAsPublishedAsync(evt.Id); - } - catch (Exception ex) - { - _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", evt.Id, Program.AppName, evt); - await _eventLogService.MarkEventAsFailedAsync(evt.Id); - } + _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", evt.Id, Program.AppName, evt); + await _eventLogService.MarkEventAsFailedAsync(evt.Id); } + } - public async Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt) - { - _logger.LogInformation("----- CatalogIntegrationEventService - Saving changes and integrationEvent: {IntegrationEventId}", evt.Id); + public async Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt) + { + _logger.LogInformation("----- CatalogIntegrationEventService - Saving changes and integrationEvent: {IntegrationEventId}", evt.Id); - //Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction(): - //See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - await ResilientTransaction.New(_catalogContext).ExecuteAsync(async () => - { - // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction - await _catalogContext.SaveChangesAsync(); - await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction); - }); - } + //Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction(): + //See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + await ResilientTransaction.New(_catalogContext).ExecuteAsync(async () => + { + // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction + await _catalogContext.SaveChangesAsync(); + await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction); + }); + } - protected virtual void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) { - if (!disposedValue) + if (disposing) { - if (disposing) - { - (_eventLogService as IDisposable)?.Dispose(); - } - - disposedValue = true; + (_eventLogService as IDisposable)?.Dispose(); } - } - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); + disposedValue = true; } } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs index 95da93f75..35c523c39 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs @@ -1,58 +1,46 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling; + +public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : + IIntegrationEventHandler { - using BuildingBlocks.EventBus.Abstractions; - using BuildingBlocks.EventBus.Events; - using global::Catalog.API.IntegrationEvents; - using Infrastructure; - using IntegrationEvents.Events; - using Microsoft.Extensions.Logging; - using Serilog.Context; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - - public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : - IIntegrationEventHandler + private readonly CatalogContext _catalogContext; + private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; + private readonly ILogger _logger; + + public OrderStatusChangedToAwaitingValidationIntegrationEventHandler( + CatalogContext catalogContext, + ICatalogIntegrationEventService catalogIntegrationEventService, + ILogger logger) { - private readonly CatalogContext _catalogContext; - private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; - private readonly ILogger _logger; - - public OrderStatusChangedToAwaitingValidationIntegrationEventHandler( - CatalogContext catalogContext, - ICatalogIntegrationEventService catalogIntegrationEventService, - ILogger logger) - { - _catalogContext = catalogContext; - _catalogIntegrationEventService = catalogIntegrationEventService; - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - } + _catalogContext = catalogContext; + _catalogIntegrationEventService = catalogIntegrationEventService; + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var confirmedOrderStockItems = new List(); + var confirmedOrderStockItems = new List(); - foreach (var orderStockItem in @event.OrderStockItems) - { - var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId); - var hasStock = catalogItem.AvailableStock >= orderStockItem.Units; - var confirmedOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id, hasStock); + foreach (var orderStockItem in @event.OrderStockItems) + { + var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId); + var hasStock = catalogItem.AvailableStock >= orderStockItem.Units; + var confirmedOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id, hasStock); - confirmedOrderStockItems.Add(confirmedOrderStockItem); - } + confirmedOrderStockItems.Add(confirmedOrderStockItem); + } - var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.HasStock) - ? (IntegrationEvent)new OrderStockRejectedIntegrationEvent(@event.OrderId, confirmedOrderStockItems) - : new OrderStockConfirmedIntegrationEvent(@event.OrderId); + var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.HasStock) + ? (IntegrationEvent)new OrderStockRejectedIntegrationEvent(@event.OrderId, confirmedOrderStockItems) + : new OrderStockConfirmedIntegrationEvent(@event.OrderId); - await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent); - await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent); + await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent); + await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent); - } } } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs index 5a9b4a0f8..8882e78a6 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs @@ -1,43 +1,35 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling; + +public class OrderStatusChangedToPaidIntegrationEventHandler : + IIntegrationEventHandler { - using BuildingBlocks.EventBus.Abstractions; - using Infrastructure; - using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; - using Microsoft.Extensions.Logging; - using Serilog.Context; - using System.Threading.Tasks; + private readonly CatalogContext _catalogContext; + private readonly ILogger _logger; - public class OrderStatusChangedToPaidIntegrationEventHandler : - IIntegrationEventHandler + public OrderStatusChangedToPaidIntegrationEventHandler( + CatalogContext catalogContext, + ILogger logger) { - private readonly CatalogContext _catalogContext; - private readonly ILogger _logger; + _catalogContext = catalogContext; + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + } - public OrderStatusChangedToPaidIntegrationEventHandler( - CatalogContext catalogContext, - ILogger logger) + public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - _catalogContext = catalogContext; - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - } + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event) - { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) + //we're not blocking stock/inventory + foreach (var orderStockItem in @event.OrderStockItems) { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - - //we're not blocking stock/inventory - foreach (var orderStockItem in @event.OrderStockItems) - { - var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId); + var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId); - catalogItem.RemoveStock(orderStockItem.Units); - } + catalogItem.RemoveStock(orderStockItem.Units); + } - await _catalogContext.SaveChangesAsync(); + await _catalogContext.SaveChangesAsync(); - } } } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs index b1061f60e..925b5fbcc 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs @@ -1,30 +1,26 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; + +public record OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent { - using BuildingBlocks.EventBus.Events; - using System.Collections.Generic; + public int OrderId { get; } + public IEnumerable OrderStockItems { get; } - public record OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent + public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, + IEnumerable orderStockItems) { - public int OrderId { get; } - public IEnumerable OrderStockItems { get; } - - public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, - IEnumerable orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - } + OrderId = orderId; + OrderStockItems = orderStockItems; } +} - public record OrderStockItem - { - public int ProductId { get; } - public int Units { get; } +public record OrderStockItem +{ + public int ProductId { get; } + public int Units { get; } - public OrderStockItem(int productId, int units) - { - ProductId = productId; - Units = units; - } + public OrderStockItem(int productId, int units) + { + ProductId = productId; + Units = units; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs index b89465f7a..1ca5cc6db 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs @@ -1,18 +1,14 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; + +public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using System.Collections.Generic; + public int OrderId { get; } + public IEnumerable OrderStockItems { get; } - public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent + public OrderStatusChangedToPaidIntegrationEvent(int orderId, + IEnumerable orderStockItems) { - public int OrderId { get; } - public IEnumerable OrderStockItems { get; } - - public OrderStatusChangedToPaidIntegrationEvent(int orderId, - IEnumerable orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - } + OrderId = orderId; + OrderStockItems = orderStockItems; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs index 6c6a3cfa4..30e4dfce2 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs @@ -1,11 +1,8 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events -{ - using BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; - public record OrderStockConfirmedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderStockConfirmedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public OrderStockConfirmedIntegrationEvent(int orderId) => OrderId = orderId; - } -} \ No newline at end of file + public OrderStockConfirmedIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs index 7c098edf4..7c8d03b18 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs @@ -1,31 +1,27 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events -{ - using BuildingBlocks.EventBus.Events; - using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; - public record OrderStockRejectedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderStockRejectedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public List OrderStockItems { get; } + public List OrderStockItems { get; } - public OrderStockRejectedIntegrationEvent(int orderId, - List orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - } + public OrderStockRejectedIntegrationEvent(int orderId, + List orderStockItems) + { + OrderId = orderId; + OrderStockItems = orderStockItems; } +} - public record ConfirmedOrderStockItem - { - public int ProductId { get; } - public bool HasStock { get; } +public record ConfirmedOrderStockItem +{ + public int ProductId { get; } + public bool HasStock { get; } - public ConfirmedOrderStockItem(int productId, bool hasStock) - { - ProductId = productId; - HasStock = hasStock; - } + public ConfirmedOrderStockItem(int productId, bool hasStock) + { + ProductId = productId; + HasStock = hasStock; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs index 9f1f504af..69a821935 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs @@ -1,23 +1,20 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events -{ - using BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; - // Integration Events notes: - // An Event is “something that has happened in the past”, therefore its name has to be past tense - // An Integration Event is an event that can cause side effects to other microservices, Bounded-Contexts or external systems. - public record ProductPriceChangedIntegrationEvent : IntegrationEvent - { - public int ProductId { get; private init; } +// Integration Events notes: +// An Event is “something that has happened in the past”, therefore its name has to be past tense +// An Integration Event is an event that can cause side effects to other microservices, Bounded-Contexts or external systems. +public record ProductPriceChangedIntegrationEvent : IntegrationEvent +{ + public int ProductId { get; private init; } - public decimal NewPrice { get; private init; } + public decimal NewPrice { get; private init; } - public decimal OldPrice { get; private init; } + public decimal OldPrice { get; private init; } - public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice) - { - ProductId = productId; - NewPrice = newPrice; - OldPrice = oldPrice; - } + public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice) + { + ProductId = productId; + NewPrice = newPrice; + OldPrice = oldPrice; } } diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs index 4d87e8e94..f5e78b803 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/ICatalogIntegrationEventService.cs @@ -1,11 +1,7 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents; -namespace Catalog.API.IntegrationEvents +public interface ICatalogIntegrationEventService { - public interface ICatalogIntegrationEventService - { - Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt); - Task PublishThroughEventBusAsync(IntegrationEvent evt); - } + Task SaveEventAndCatalogContextChangesAsync(IntegrationEvent evt); + Task PublishThroughEventBusAsync(IntegrationEvent evt); } diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs b/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs index 84d72899e..68223177e 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogBrand.cs @@ -1,9 +1,8 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model; + +public class CatalogBrand { - public class CatalogBrand - { - public int Id { get; set; } + public int Id { get; set; } - public string Brand { get; set; } - } + public string Brand { get; set; } } diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs b/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs index 2e4579f7f..f5a4f9654 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogItem.cs @@ -1,103 +1,99 @@ -using Catalog.API.Infrastructure.Exceptions; -using System; +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model; -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model +public class CatalogItem { - public class CatalogItem - { - public int Id { get; set; } + public int Id { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public string Description { get; set; } + public string Description { get; set; } - public decimal Price { get; set; } + public decimal Price { get; set; } - public string PictureFileName { get; set; } + public string PictureFileName { get; set; } - public string PictureUri { get; set; } + public string PictureUri { get; set; } - public int CatalogTypeId { get; set; } + public int CatalogTypeId { get; set; } - public CatalogType CatalogType { get; set; } + public CatalogType CatalogType { get; set; } - public int CatalogBrandId { get; set; } + public int CatalogBrandId { get; set; } - public CatalogBrand CatalogBrand { get; set; } + public CatalogBrand CatalogBrand { get; set; } - // Quantity in stock - public int AvailableStock { get; set; } + // Quantity in stock + public int AvailableStock { get; set; } - // Available stock at which we should reorder - public int RestockThreshold { get; set; } + // Available stock at which we should reorder + public int RestockThreshold { get; set; } - // Maximum number of units that can be in-stock at any time (due to physicial/logistical constraints in warehouses) - public int MaxStockThreshold { get; set; } + // Maximum number of units that can be in-stock at any time (due to physicial/logistical constraints in warehouses) + public int MaxStockThreshold { get; set; } - /// - /// True if item is on reorder - /// - public bool OnReorder { get; set; } + /// + /// True if item is on reorder + /// + public bool OnReorder { get; set; } - public CatalogItem() { } + public CatalogItem() { } - /// - /// Decrements the quantity of a particular item in inventory and ensures the restockThreshold hasn't - /// been breached. If so, a RestockRequest is generated in CheckThreshold. - /// - /// If there is sufficient stock of an item, then the integer returned at the end of this call should be the same as quantityDesired. - /// In the event that there is not sufficient stock available, the method will remove whatever stock is available and return that quantity to the client. - /// In this case, it is the responsibility of the client to determine if the amount that is returned is the same as quantityDesired. - /// It is invalid to pass in a negative number. - /// - /// - /// int: Returns the number actually removed from stock. - /// - public int RemoveStock(int quantityDesired) + /// + /// Decrements the quantity of a particular item in inventory and ensures the restockThreshold hasn't + /// been breached. If so, a RestockRequest is generated in CheckThreshold. + /// + /// If there is sufficient stock of an item, then the integer returned at the end of this call should be the same as quantityDesired. + /// In the event that there is not sufficient stock available, the method will remove whatever stock is available and return that quantity to the client. + /// In this case, it is the responsibility of the client to determine if the amount that is returned is the same as quantityDesired. + /// It is invalid to pass in a negative number. + /// + /// + /// int: Returns the number actually removed from stock. + /// + public int RemoveStock(int quantityDesired) + { + if (AvailableStock == 0) { - if (AvailableStock == 0) - { - throw new CatalogDomainException($"Empty stock, product item {Name} is sold out"); - } + throw new CatalogDomainException($"Empty stock, product item {Name} is sold out"); + } - if (quantityDesired <= 0) - { - throw new CatalogDomainException($"Item units desired should be greater than zero"); - } + if (quantityDesired <= 0) + { + throw new CatalogDomainException($"Item units desired should be greater than zero"); + } - int removed = Math.Min(quantityDesired, this.AvailableStock); + int removed = Math.Min(quantityDesired, this.AvailableStock); - this.AvailableStock -= removed; + this.AvailableStock -= removed; - return removed; - } + return removed; + } - /// - /// Increments the quantity of a particular item in inventory. - /// - /// int: Returns the quantity that has been added to stock - /// - public int AddStock(int quantity) + /// + /// Increments the quantity of a particular item in inventory. + /// + /// int: Returns the quantity that has been added to stock + /// + public int AddStock(int quantity) + { + int original = this.AvailableStock; + + // The quantity that the client is trying to add to stock is greater than what can be physically accommodated in the Warehouse + if ((this.AvailableStock + quantity) > this.MaxStockThreshold) + { + // For now, this method only adds new units up maximum stock threshold. In an expanded version of this application, we + //could include tracking for the remaining units and store information about overstock elsewhere. + this.AvailableStock += (this.MaxStockThreshold - this.AvailableStock); + } + else { - int original = this.AvailableStock; - - // The quantity that the client is trying to add to stock is greater than what can be physically accommodated in the Warehouse - if ((this.AvailableStock + quantity) > this.MaxStockThreshold) - { - // For now, this method only adds new units up maximum stock threshold. In an expanded version of this application, we - //could include tracking for the remaining units and store information about overstock elsewhere. - this.AvailableStock += (this.MaxStockThreshold - this.AvailableStock); - } - else - { - this.AvailableStock += quantity; - } - - this.OnReorder = false; - - return this.AvailableStock - original; + this.AvailableStock += quantity; } + + this.OnReorder = false; + + return this.AvailableStock - original; } -} \ No newline at end of file +} diff --git a/src/Services/Catalog/Catalog.API/Model/CatalogType.cs b/src/Services/Catalog/Catalog.API/Model/CatalogType.cs index 0bc640dee..17754536e 100644 --- a/src/Services/Catalog/Catalog.API/Model/CatalogType.cs +++ b/src/Services/Catalog/Catalog.API/Model/CatalogType.cs @@ -1,9 +1,8 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model +namespace Microsoft.eShopOnContainers.Services.Catalog.API.Model; + +public class CatalogType { - public class CatalogType - { - public int Id { get; set; } + public int Id { get; set; } - public string Type { get; set; } - } + public string Type { get; set; } } diff --git a/src/Services/Catalog/Catalog.API/Pics/1.png b/src/Services/Catalog/Catalog.API/Pics/1.png index 2db4977f3..ee1e52331 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/1.png and b/src/Services/Catalog/Catalog.API/Pics/1.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/10.png b/src/Services/Catalog/Catalog.API/Pics/10.png index f3f411c98..8d4660c7b 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/10.png and b/src/Services/Catalog/Catalog.API/Pics/10.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/11.png b/src/Services/Catalog/Catalog.API/Pics/11.png index 2b8c52068..a9f8d6592 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/11.png and b/src/Services/Catalog/Catalog.API/Pics/11.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/12.png b/src/Services/Catalog/Catalog.API/Pics/12.png index 73da17e8f..9a083b985 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/12.png and b/src/Services/Catalog/Catalog.API/Pics/12.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/13.png b/src/Services/Catalog/Catalog.API/Pics/13.png new file mode 100644 index 000000000..7ae7f60b0 Binary files /dev/null and b/src/Services/Catalog/Catalog.API/Pics/13.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/14.png b/src/Services/Catalog/Catalog.API/Pics/14.png new file mode 100644 index 000000000..f81166783 Binary files /dev/null and b/src/Services/Catalog/Catalog.API/Pics/14.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/2.png b/src/Services/Catalog/Catalog.API/Pics/2.png index 8446fad15..40b2a9e28 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/2.png and b/src/Services/Catalog/Catalog.API/Pics/2.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/3.png b/src/Services/Catalog/Catalog.API/Pics/3.png index 7f91f6fb2..c5f68436e 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/3.png and b/src/Services/Catalog/Catalog.API/Pics/3.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/4.png b/src/Services/Catalog/Catalog.API/Pics/4.png index d6bd62201..2002cd716 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/4.png and b/src/Services/Catalog/Catalog.API/Pics/4.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/5.png b/src/Services/Catalog/Catalog.API/Pics/5.png index ed2940d29..bae3dab35 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/5.png and b/src/Services/Catalog/Catalog.API/Pics/5.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/6.png b/src/Services/Catalog/Catalog.API/Pics/6.png index f9ed57d63..3960c1e7d 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/6.png and b/src/Services/Catalog/Catalog.API/Pics/6.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/7.png b/src/Services/Catalog/Catalog.API/Pics/7.png index 9ed499fc5..2c0a89e30 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/7.png and b/src/Services/Catalog/Catalog.API/Pics/7.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/8.png b/src/Services/Catalog/Catalog.API/Pics/8.png index 08d60e14a..fede0db7f 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/8.png and b/src/Services/Catalog/Catalog.API/Pics/8.png differ diff --git a/src/Services/Catalog/Catalog.API/Pics/9.png b/src/Services/Catalog/Catalog.API/Pics/9.png index 1f33c47e7..417ec0f28 100644 Binary files a/src/Services/Catalog/Catalog.API/Pics/9.png and b/src/Services/Catalog/Catalog.API/Pics/9.png differ diff --git a/src/Services/Catalog/Catalog.API/Program.cs b/src/Services/Catalog/Catalog.API/Program.cs index 1507b1d8e..e5ef82aff 100644 --- a/src/Services/Catalog/Catalog.API/Program.cs +++ b/src/Services/Catalog/Catalog.API/Program.cs @@ -1,21 +1,4 @@ -using Catalog.API.Extensions; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.Services.Catalog.API; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Serilog; -using System; -using System.IO; -using System.Net; - -var configuration = GetConfiguration(); +var configuration = GetConfiguration(); Log.Logger = CreateSerilogLogger(configuration); @@ -31,9 +14,7 @@ try var settings = services.GetService>(); var logger = services.GetService>(); - new CatalogContextSeed() - .SeedAsync(context, env, settings, logger) - .Wait(); + new CatalogContextSeed().SeedAsync(context, env, settings, logger).Wait(); }) .MigrateDbContext((_, __) => { }); @@ -108,16 +89,17 @@ IConfiguration GetConfiguration() if (config.GetValue("UseVault", false)) { - builder.AddAzureKeyVault( - $"https://{config["Vault:Name"]}.vault.azure.net/", + TokenCredential credential = new ClientSecretCredential( + config["Vault:TenantId"], config["Vault:ClientId"], config["Vault:ClientSecret"]); + //builder.AddAzureKeyVault(new Uri($"https://{config["Vault:Name"]}.vault.azure.net/"), credential); } return builder.Build(); } -public static class Program +public partial class Program { public static string Namespace = typeof(Startup).Namespace; public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); diff --git a/src/Services/Catalog/Catalog.API/Setup/CatalogBrands.csv b/src/Services/Catalog/Catalog.API/Setup/CatalogBrands.csv index 95c9ee64c..2e6571fb1 100644 --- a/src/Services/Catalog/Catalog.API/Setup/CatalogBrands.csv +++ b/src/Services/Catalog/Catalog.API/Setup/CatalogBrands.csv @@ -1,8 +1,3 @@ CatalogBrand -Azure .NET -Visual Studio -SQL Server Other -CatalogBrandTestOne -CatalogBrandTestTwo \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Setup/CatalogItems-MVC.zip b/src/Services/Catalog/Catalog.API/Setup/CatalogItems-MVC.zip new file mode 100644 index 000000000..1bacd405c Binary files /dev/null and b/src/Services/Catalog/Catalog.API/Setup/CatalogItems-MVC.zip differ diff --git a/src/Services/Catalog/Catalog.API/Setup/CatalogItems-SPA.zip b/src/Services/Catalog/Catalog.API/Setup/CatalogItems-SPA.zip new file mode 100644 index 000000000..5a2099705 Binary files /dev/null and b/src/Services/Catalog/Catalog.API/Setup/CatalogItems-SPA.zip differ diff --git a/src/Services/Catalog/Catalog.API/Setup/CatalogItems.csv b/src/Services/Catalog/Catalog.API/Setup/CatalogItems.csv index 430d52f20..cf2054ba7 100644 --- a/src/Services/Catalog/Catalog.API/Setup/CatalogItems.csv +++ b/src/Services/Catalog/Catalog.API/Setup/CatalogItems.csv @@ -3,12 +3,13 @@ T-Shirt,.NET,".NET Bot Black Hoodie, and more",.NET Bot Black Hoodie,19.5,1.png, Mug,.NET,.NET Black & White Mug,.NET Black & White Mug,8.50,2.png,89,true T-Shirt,Other,Prism White T-Shirt,Prism White T-Shirt,12,3.png,56,false T-Shirt,.NET,.NET Foundation T-shirt,.NET Foundation T-shirt,12,4.png,120,false -Sheet,Other,Roslyn Red Sheet,Roslyn Red Sheet,8.5,5.png,55,false +Pin,Other,Roslyn Red Pin,Roslyn Red Pin,8.5,5.png,55,false T-Shirt,.NET,.NET Blue Hoodie,.NET Blue Hoodie,12,6.png,17,false T-Shirt,Other,Roslyn Red T-Shirt,Roslyn Red T-Shirt,12,7.png,8,false T-Shirt,Other,Kudu Purple Hoodie,Kudu Purple Hoodie,8.5,8.png,34,false Mug,Other,Cup White Mug,Cup White Mug,12,9.png,76,false -Sheet,.NET,.NET Foundation Sheet,.NET Foundation Sheet,12,10.png,11,false -Sheet,.NET,Cup Sheet,Cup Sheet,8.5,11.png,3,false +Pin,.NET,.NET Foundation Pin,.NET Foundation Pin,12,10.png,11,false +Pin,.NET,Cup Pin,Cup Pin,8.5,11.png,3,false T-Shirt,Other,Prism White TShirt,Prism White TShirt,12,12.png,0,false -Mug, Other, De los Palotes, pepito, 12, 12.png, 0, false \ No newline at end of file +Mug,.NET,Modern .NET Black & White Mug,Modern .NET Black & White Mug,8.50,13.png,89,true +Mug,Other,Modern Cup White Mug,Modern Cup White Mug,12,14.png,76,false diff --git a/src/Services/Catalog/Catalog.API/Setup/CatalogItems.zip b/src/Services/Catalog/Catalog.API/Setup/CatalogItems.zip index 6d3edfb3c..5a2099705 100644 Binary files a/src/Services/Catalog/Catalog.API/Setup/CatalogItems.zip and b/src/Services/Catalog/Catalog.API/Setup/CatalogItems.zip differ diff --git a/src/Services/Catalog/Catalog.API/Setup/CatalogTypes.csv b/src/Services/Catalog/Catalog.API/Setup/CatalogTypes.csv index ae636c265..fc2bac68c 100644 --- a/src/Services/Catalog/Catalog.API/Setup/CatalogTypes.csv +++ b/src/Services/Catalog/Catalog.API/Setup/CatalogTypes.csv @@ -1,7 +1,4 @@ CatalogType Mug T-Shirt -Sheet -USB Memory Stick -CatalogTypeTestOne -CatalogTypeTestTwo \ No newline at end of file +Pin \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Setup/README.md b/src/Services/Catalog/Catalog.API/Setup/README.md new file mode 100644 index 000000000..e3c5cccbc --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Setup/README.md @@ -0,0 +1,10 @@ +# Catalog set up + +The catalog images have been updated to the new SPA looks. + +If you want to use the classical images: + +1. Drop the `Microsoft.eShopOnContainers.Services.CatalogDb` database from the `sqldata` container. +2. Rename `CatalogItems-MVC.zip` as `CatalogItems.zip` +3. Rebuild the `catalog-api` service with `docker-compose build catalog-api` +4. Restart the application as usual diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 557183e38..f7b46cb6f 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -1,368 +1,333 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using Catalog.API.Grpc; -using global::Catalog.API.Infrastructure.Filters; -using global::Catalog.API.IntegrationEvents; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Azure.ServiceBus; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling; -using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; -using RabbitMQ.Client; -using System; -using System.Data.Common; -using System.IO; -using System.Reflection; - -namespace Microsoft.eShopOnContainers.Services.Catalog.API +namespace Microsoft.eShopOnContainers.Services.Catalog.API; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - public IServiceProvider ConfigureServices(IServiceCollection services) - { - services.AddAppInsight(Configuration) - .AddGrpc().Services - .AddCustomMVC(Configuration) - .AddCustomDbContext(Configuration) - .AddCustomOptions(Configuration) - .AddIntegrationServices(Configuration) - .AddEventBus(Configuration) - .AddSwagger(Configuration) - .AddCustomHealthCheck(Configuration); - - var container = new ContainerBuilder(); - container.Populate(services); - - return new AutofacServiceProvider(container.Build()); - } + public IServiceProvider ConfigureServices(IServiceCollection services) + { + services.AddAppInsight(Configuration) + .AddGrpc().Services + .AddCustomMVC(Configuration) + .AddCustomDbContext(Configuration) + .AddCustomOptions(Configuration) + .AddIntegrationServices(Configuration) + .AddEventBus(Configuration) + .AddSwagger(Configuration) + .AddCustomHealthCheck(Configuration); + + var container = new ContainerBuilder(); + container.Populate(services); + + return new AutofacServiceProvider(container.Build()); + } - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) - { - //Configure logs + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + //Configure logs - //loggerFactory.AddAzureWebAppDiagnostics(); - //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + //loggerFactory.AddAzureWebAppDiagnostics(); + //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - var pathBase = Configuration["PATH_BASE"]; + var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) + if (!string.IsNullOrEmpty(pathBase)) + { + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); + } + + app.UseSwagger() + .UseSwaggerUI(c => { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); - app.UsePathBase(pathBase); - } - - app.UseSwagger() - .UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Catalog.API V1"); - }); - - app.UseRouting(); - app.UseCors("CorsPolicy"); - app.UseEndpoints(endpoints => + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Catalog.API V1"); + }); + + app.UseRouting(); + app.UseCors("CorsPolicy"); + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapGet("/_proto/", async ctx => { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapGet("/_proto/", async ctx => + ctx.Response.ContentType = "text/plain"; + using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "catalog.proto"), FileMode.Open, FileAccess.Read); + using var sr = new StreamReader(fs); + while (!sr.EndOfStream) { - ctx.Response.ContentType = "text/plain"; - using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "catalog.proto"), FileMode.Open, FileAccess.Read); - using var sr = new StreamReader(fs); - while (!sr.EndOfStream) + var line = await sr.ReadLineAsync(); + if (line != "/* >>" || line != "<< */") { - var line = await sr.ReadLineAsync(); - if (line != "/* >>" || line != "<< */") - { - await ctx.Response.WriteAsync(line); - } + await ctx.Response.WriteAsync(line); } - }); - endpoints.MapGrpcService(); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); + } + }); + endpoints.MapGrpcService(); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions + { + Predicate = r => r.Name.Contains("self") }); + }); - ConfigureEventBus(app); - } + ConfigureEventBus(app); + } - protected virtual void ConfigureEventBus(IApplicationBuilder app) - { - var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe(); - eventBus.Subscribe(); - } + protected virtual void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + eventBus.Subscribe(); + eventBus.Subscribe(); } +} - public static class CustomExtensionMethods +public static class CustomExtensionMethods +{ + public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) - { - services.AddApplicationInsightsTelemetry(configuration); - services.AddApplicationInsightsKubernetesEnricher(); + services.AddApplicationInsightsTelemetry(configuration); + services.AddApplicationInsightsKubernetesEnricher(); - return services; - } + return services; + } - public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration) + { + services.AddControllers(options => { - services.AddControllers(options => - { - options.Filters.Add(typeof(HttpGlobalExceptionFilter)); - }).AddNewtonsoftJson(); + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + }) + .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .SetIsOriginAllowed((host) => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } - return services; - } + public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) + { + var accountName = configuration.GetValue("AzureStorageAccountName"); + var accountKey = configuration.GetValue("AzureStorageAccountKey"); - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var accountName = configuration.GetValue("AzureStorageAccountName"); - var accountKey = configuration.GetValue("AzureStorageAccountKey"); + var hcBuilder = services.AddHealthChecks(); - var hcBuilder = services.AddHealthChecks(); + hcBuilder + .AddCheck("self", () => HealthCheckResult.Healthy()) + .AddSqlServer( + configuration["ConnectionString"], + name: "CatalogDB-check", + tags: new string[] { "catalogdb" }); + if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey)) + { hcBuilder - .AddCheck("self", () => HealthCheckResult.Healthy()) - .AddSqlServer( - configuration["ConnectionString"], - name: "CatalogDB-check", - tags: new string[] { "catalogdb" }); - - if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey)) - { - hcBuilder - .AddAzureBlobStorage( - $"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net", - name: "catalog-storage-check", - tags: new string[] { "catalogstorage" }); - } - - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "catalog-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "catalog-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } - - return services; + .AddAzureBlobStorage( + $"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net", + name: "catalog-storage-check", + tags: new string[] { "catalogstorage" }); } - public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + if (configuration.GetValue("AzureServiceBusEnabled")) { - services.AddEntityFrameworkSqlServer() - .AddDbContext(options => - { - options.UseSqlServer(configuration["ConnectionString"], - sqlServerOptionsAction: sqlOptions => - { - sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - }); - }); + hcBuilder + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "catalog-servicebus-check", + tags: new string[] { "servicebus" }); + } + else + { + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "catalog-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); + } - services.AddDbContext(options => - { - options.UseSqlServer(configuration["ConnectionString"], - sqlServerOptionsAction: sqlOptions => - { - sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - }); - }); + return services; + } - return services; - } + public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + { + services.AddEntityFrameworkSqlServer() + .AddDbContext(options => + { + options.UseSqlServer(configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }); + + services.AddDbContext(options => + { + options.UseSqlServer(configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }); + + return services; + } - public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) + { + services.Configure(configuration); + services.Configure(options => { - services.Configure(configuration); - services.Configure(options => + options.InvalidModelStateResponseFactory = context => { - options.InvalidModelStateResponseFactory = context => + var problemDetails = new ValidationProblemDetails(context.ModelState) { - var problemDetails = new ValidationProblemDetails(context.ModelState) - { - Instance = context.HttpContext.Request.Path, - Status = StatusCodes.Status400BadRequest, - Detail = "Please refer to the errors property for additional details." - }; + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; - return new BadRequestObjectResult(problemDetails) - { - ContentTypes = { "application/problem+json", "application/problem+xml" } - }; + return new BadRequestObjectResult(problemDetails) + { + ContentTypes = { "application/problem+json", "application/problem+xml" } }; - }); + }; + }); - return services; - } + return services; + } - public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) - { - services.AddSwaggerGen(options => + public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) + { + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "eShopOnContainers - Catalog HTTP API", - Version = "v1", - Description = "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample" - }); + Title = "eShopOnContainers - Catalog HTTP API", + Version = "v1", + Description = "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample" }); + }); - return services; + return services; - } + } - public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) - { - services.AddTransient>( - sp => (DbConnection c) => new IntegrationEventLogService(c)); + public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) + { + services.AddTransient>( + sp => (DbConnection c) => new IntegrationEventLogService(c)); - services.AddTransient(); + services.AddTransient(); - if (configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var settings = sp.GetRequiredService>().Value; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(settings.EventBusConnection); - var subscriptionClientName = configuration["SubscriptionClientName"]; - - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); - }); - } - else + if (configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var settings = sp.GetRequiredService>().Value; - var logger = sp.GetRequiredService>(); + var settings = sp.GetRequiredService>().Value; + var serviceBusConnection = settings.EventBusConnection; - var factory = new ConnectionFactory() - { - HostName = configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; + return new DefaultServiceBusPersisterConnection(serviceBusConnection); + }); + } + else + { + services.AddSingleton(sp => + { + var settings = sp.GetRequiredService>().Value; + var logger = sp.GetRequiredService>(); - if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) - { - factory.UserName = configuration["EventBusUserName"]; - } + var factory = new ConnectionFactory() + { + HostName = configuration["EventBusConnection"], + DispatchConsumersAsync = true + }; - if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) - { - factory.Password = configuration["EventBusPassword"]; - } + if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) + { + factory.UserName = configuration["EventBusUserName"]; + } - var retryCount = 5; - if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(configuration["EventBusRetryCount"]); - } + if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) + { + factory.Password = configuration["EventBusPassword"]; + } - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } - return services; + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); + }); } - public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + return services; + } + + public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + { + if (configuration.GetValue("AzureServiceBusEnabled")) { - if (configuration.GetValue("AzureServiceBusEnabled")) + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, iLifetimeScope); - }); + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); + }); - } - else + } + else + { + services.AddSingleton(sp => { - services.AddSingleton(sp => + var subscriptionClientName = configuration["SubscriptionClientName"]; + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) { - var subscriptionClientName = configuration["SubscriptionClientName"]; - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(configuration["EventBusRetryCount"]); - } + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } - services.AddSingleton(); - services.AddTransient(); - services.AddTransient(); + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); - return services; - } + return services; } -} +} \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/ViewModel/PaginatedItemsViewModel.cs b/src/Services/Catalog/Catalog.API/ViewModel/PaginatedItemsViewModel.cs index d088d5bb7..d6673012b 100644 --- a/src/Services/Catalog/Catalog.API/ViewModel/PaginatedItemsViewModel.cs +++ b/src/Services/Catalog/Catalog.API/ViewModel/PaginatedItemsViewModel.cs @@ -1,24 +1,20 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel -{ - using System.Collections.Generic; - +namespace Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel; - public class PaginatedItemsViewModel where TEntity : class - { - public int PageIndex { get; private set; } +public class PaginatedItemsViewModel where TEntity : class +{ + public int PageIndex { get; private set; } - public int PageSize { get; private set; } + public int PageSize { get; private set; } - public long Count { get; private set; } + public long Count { get; private set; } - public IEnumerable Data { get; private set; } + public IEnumerable Data { get; private set; } - public PaginatedItemsViewModel(int pageIndex, int pageSize, long count, IEnumerable data) - { - PageIndex = pageIndex; - PageSize = pageSize; - Count = count; - Data = data; - } + public PaginatedItemsViewModel(int pageIndex, int pageSize, long count, IEnumerable data) + { + PageIndex = pageIndex; + PageSize = pageSize; + Count = count; + Data = data; } } diff --git a/src/Services/Catalog/Catalog.API/appsettings.json b/src/Services/Catalog/Catalog.API/appsettings.json index e9103c7a6..f8342fe8d 100644 --- a/src/Services/Catalog/Catalog.API/appsettings.json +++ b/src/Services/Catalog/Catalog.API/appsettings.json @@ -22,9 +22,9 @@ "UseVault": false, "Vault": { "Name": "eshop", - "ClientId": "your-clien-id", + "ClientId": "your-client-id", "ClientSecret": "your-client-secret" } } - \ No newline at end of file + diff --git a/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj b/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj index 4c582eba6..cb8ec5630 100644 --- a/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj +++ b/src/Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false @@ -33,8 +33,8 @@ - - + + all diff --git a/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarioBase.cs b/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarioBase.cs index 8545d14aa..793d170ae 100644 --- a/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarioBase.cs +++ b/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarioBase.cs @@ -1,93 +1,78 @@ -using Catalog.API.Extensions; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.Services.Catalog.API; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.IO; -using System.Reflection; +namespace Catalog.FunctionalTests; -namespace Catalog.FunctionalTests +public class CatalogScenariosBase { - public class CatalogScenariosBase + public TestServer CreateServer() { - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(CatalogScenariosBase)) - .Location; + var path = Assembly.GetAssembly(typeof(CatalogScenariosBase)) + .Location; - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("appsettings.json", optional: false) - .AddEnvironmentVariables(); - }) - .UseStartup(); + var hostBuilder = new WebHostBuilder() + .UseContentRoot(Path.GetDirectoryName(path)) + .ConfigureAppConfiguration(cb => + { + cb.AddJsonFile("appsettings.json", optional: false) + .AddEnvironmentVariables(); + }) + .UseStartup(); - var testServer = new TestServer(hostBuilder); + var testServer = new TestServer(hostBuilder); - testServer.Host - .MigrateDbContext((context, services) => - { - var env = services.GetService(); - var settings = services.GetService>(); - var logger = services.GetService>(); + testServer.Host + .MigrateDbContext((context, services) => + { + var env = services.GetService(); + var settings = services.GetService>(); + var logger = services.GetService>(); - new CatalogContextSeed() - .SeedAsync(context, env, settings, logger) - .Wait(); - }) - .MigrateDbContext((_, __) => { }); + new CatalogContextSeed() + .SeedAsync(context, env, settings, logger) + .Wait(); + }) + .MigrateDbContext((_, __) => { }); - return testServer; - } + return testServer; + } - public static class Get - { - private const int PageIndex = 0; - private const int PageCount = 4; + public static class Get + { + private const int PageIndex = 0; + private const int PageCount = 4; - public static string Items(bool paginated = false) - { - return paginated - ? "api/v1/catalog/items" + Paginated(PageIndex, PageCount) - : "api/v1/catalog/items"; - } + public static string Items(bool paginated = false) + { + return paginated + ? "api/v1/catalog/items" + Paginated(PageIndex, PageCount) + : "api/v1/catalog/items"; + } - public static string ItemById(int id) - { - return $"api/v1/catalog/items/{id}"; - } + public static string ItemById(int id) + { + return $"api/v1/catalog/items/{id}"; + } - public static string ItemByName(string name, bool paginated = false) - { - return paginated - ? $"api/v1/catalog/items/withname/{name}" + Paginated(PageIndex, PageCount) - : $"api/v1/catalog/items/withname/{name}"; - } + public static string ItemByName(string name, bool paginated = false) + { + return paginated + ? $"api/v1/catalog/items/withname/{name}" + Paginated(PageIndex, PageCount) + : $"api/v1/catalog/items/withname/{name}"; + } - public static string Types = "api/v1/catalog/catalogtypes"; + public static string Types = "api/v1/catalog/catalogtypes"; - public static string Brands = "api/v1/catalog/catalogbrands"; + public static string Brands = "api/v1/catalog/catalogbrands"; - public static string Filtered(int catalogTypeId, int catalogBrandId, bool paginated = false) - { - return paginated - ? $"api/v1/catalog/items/type/{catalogTypeId}/brand/{catalogBrandId}" + Paginated(PageIndex, PageCount) - : $"api/v1/catalog/items/type/{catalogTypeId}/brand/{catalogBrandId}"; - } + public static string Filtered(int catalogTypeId, int catalogBrandId, bool paginated = false) + { + return paginated + ? $"api/v1/catalog/items/type/{catalogTypeId}/brand/{catalogBrandId}" + Paginated(PageIndex, PageCount) + : $"api/v1/catalog/items/type/{catalogTypeId}/brand/{catalogBrandId}"; + } - private static string Paginated(int pageIndex, int pageCount) - { - return $"?pageIndex={pageIndex}&pageSize={pageCount}"; - } + private static string Paginated(int pageIndex, int pageCount) + { + return $"?pageIndex={pageIndex}&pageSize={pageCount}"; } } } diff --git a/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs b/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs index abb6a6cbf..956d29403 100644 --- a/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs +++ b/src/Services/Catalog/Catalog.FunctionalTests/CatalogScenarios.cs @@ -1,145 +1,118 @@ -using System.Net; -using System.Threading.Tasks; -using Xunit; +namespace Catalog.FunctionalTests; -namespace Catalog.FunctionalTests +public class CatalogScenarios + : CatalogScenariosBase { - public class CatalogScenarios - : CatalogScenariosBase + [Fact] + public async Task Get_get_all_catalogitems_and_response_ok_status_code() { - [Fact] - public async Task Get_get_all_catalogitems_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Items()); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_get_catalogitem_by_id_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemById(1)); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_get_catalogitem_by_id_and_response_bad_request_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemById(int.MinValue)); - - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } - } - - [Fact] - public async Task Get_get_catalogitem_by_id_and_response_not_found_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemById(int.MaxValue)); - - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } - } - - [Fact] - public async Task Get_get_catalogitem_by_name_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.ItemByName(".NET")); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_get_paginated_catalogitem_by_name_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - const bool paginated = true; - var response = await server.CreateClient() - .GetAsync(Get.ItemByName(".NET", paginated)); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_get_paginated_catalog_items_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - const bool paginated = true; - var response = await server.CreateClient() - .GetAsync(Get.Items(paginated)); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_get_filtered_catalog_items_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Filtered(1, 1)); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_get_paginated_filtered_catalog_items_and_response_ok_status_code() - { - using (var server = CreateServer()) - { - const bool paginated = true; - var response = await server.CreateClient() - .GetAsync(Get.Filtered(1, 1, paginated)); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_catalog_types_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Types); - - response.EnsureSuccessStatusCode(); - } - } - - [Fact] - public async Task Get_catalog_brands_response_ok_status_code() - { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Brands); - - response.EnsureSuccessStatusCode(); - } - } + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Items()); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_get_catalogitem_by_id_and_response_ok_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemById(1)); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_get_catalogitem_by_id_and_response_bad_request_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemById(int.MinValue)); + + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); + } + + [Fact] + public async Task Get_get_catalogitem_by_id_and_response_not_found_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemById(int.MaxValue)); + + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + + [Fact] + public async Task Get_get_catalogitem_by_name_and_response_ok_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.ItemByName(".NET")); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_get_paginated_catalogitem_by_name_and_response_ok_status_code() + { + using var server = CreateServer(); + const bool paginated = true; + var response = await server.CreateClient() + .GetAsync(Get.ItemByName(".NET", paginated)); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_get_paginated_catalog_items_and_response_ok_status_code() + { + using var server = CreateServer(); + const bool paginated = true; + var response = await server.CreateClient() + .GetAsync(Get.Items(paginated)); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_get_filtered_catalog_items_and_response_ok_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Filtered(1, 1)); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_get_paginated_filtered_catalog_items_and_response_ok_status_code() + { + using var server = CreateServer(); + const bool paginated = true; + var response = await server.CreateClient() + .GetAsync(Get.Filtered(1, 1, paginated)); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_catalog_types_response_ok_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Types); + + response.EnsureSuccessStatusCode(); + } + + [Fact] + public async Task Get_catalog_brands_response_ok_status_code() + { + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Brands); + + response.EnsureSuccessStatusCode(); } } diff --git a/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs b/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs new file mode 100644 index 000000000..2ceffc535 --- /dev/null +++ b/src/Services/Catalog/Catalog.FunctionalTests/GlobalUsings.cs @@ -0,0 +1,16 @@ +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.TestHost; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Extensions; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; +global using Microsoft.eShopOnContainers.Services.Catalog.API; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using System.IO; +global using System.Net; +global using System.Reflection; +global using System.Threading.Tasks; +global using Xunit; diff --git a/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs b/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs index f7529f73c..53efafbfd 100644 --- a/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs +++ b/src/Services/Catalog/Catalog.UnitTests/Application/CatalogControllerTest.cs @@ -1,4 +1,4 @@ -using Catalog.API.IntegrationEvents; +using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.eShopOnContainers.Services.Catalog.API; @@ -13,120 +13,116 @@ using System.Linq; using System.Threading.Tasks; using Xunit; -namespace UnitTest.Catalog.Application -{ - public class CatalogControllerTest - { - private readonly DbContextOptions _dbOptions; +namespace UnitTest.Catalog.Application; - public CatalogControllerTest() - { - _dbOptions = new DbContextOptionsBuilder() - .UseInMemoryDatabase(databaseName: "in-memory") - .Options; +public class CatalogControllerTest +{ + private readonly DbContextOptions _dbOptions; - using (var dbContext = new CatalogContext(_dbOptions)) - { - dbContext.AddRange(GetFakeCatalog()); - dbContext.SaveChanges(); - } - } + public CatalogControllerTest() + { + _dbOptions = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: "in-memory") + .Options; - [Fact] - public async Task Get_catalog_items_success() - { - //Arrange - var brandFilterApplied = 1; - var typesFilterApplied = 2; - var pageSize = 4; - var pageIndex = 1; + using var dbContext = new CatalogContext(_dbOptions); + dbContext.AddRange(GetFakeCatalog()); + dbContext.SaveChanges(); + } - var expectedItemsInPage = 2; - var expectedTotalItems = 6; + [Fact] + public async Task Get_catalog_items_success() + { + //Arrange + var brandFilterApplied = 1; + var typesFilterApplied = 2; + var pageSize = 4; + var pageIndex = 1; - var catalogContext = new CatalogContext(_dbOptions); - var catalogSettings = new TestCatalogSettings(); + var expectedItemsInPage = 2; + var expectedTotalItems = 6; - var integrationServicesMock = new Mock(); + var catalogContext = new CatalogContext(_dbOptions); + var catalogSettings = new TestCatalogSettings(); - //Act - var orderController = new CatalogController(catalogContext, catalogSettings, integrationServicesMock.Object); - var actionResult = await orderController.ItemsByTypeIdAndBrandIdAsync(typesFilterApplied, brandFilterApplied, pageSize, pageIndex); + var integrationServicesMock = new Mock(); - //Assert - Assert.IsType>>(actionResult); - var page = Assert.IsAssignableFrom>(actionResult.Value); - Assert.Equal(expectedTotalItems, page.Count); - Assert.Equal(pageIndex, page.PageIndex); - Assert.Equal(pageSize, page.PageSize); - Assert.Equal(expectedItemsInPage, page.Data.Count()); - } + //Act + var orderController = new CatalogController(catalogContext, catalogSettings, integrationServicesMock.Object); + var actionResult = await orderController.ItemsByTypeIdAndBrandIdAsync(typesFilterApplied, brandFilterApplied, pageSize, pageIndex); - private List GetFakeCatalog() - { - return new List() - { - new CatalogItem() - { - Id = 1, - Name = "fakeItemA", - CatalogTypeId = 2, - CatalogBrandId = 1, - PictureFileName = "fakeItemA.png" - }, - new CatalogItem() - { - Id = 2, - Name = "fakeItemB", - CatalogTypeId = 2, - CatalogBrandId = 1, - PictureFileName = "fakeItemB.png" - }, - new CatalogItem() - { - Id = 3, - Name = "fakeItemC", - CatalogTypeId = 2, - CatalogBrandId = 1, - PictureFileName = "fakeItemC.png" - }, - new CatalogItem() - { - Id = 4, - Name = "fakeItemD", - CatalogTypeId = 2, - CatalogBrandId = 1, - PictureFileName = "fakeItemD.png" - }, - new CatalogItem() - { - Id = 5, - Name = "fakeItemE", - CatalogTypeId = 2, - CatalogBrandId = 1, - PictureFileName = "fakeItemE.png" - }, - new CatalogItem() - { - Id = 6, - Name = "fakeItemF", - CatalogTypeId = 2, - CatalogBrandId = 1, - PictureFileName = "fakeItemF.png" - } - }; - } + //Assert + Assert.IsType>>(actionResult); + var page = Assert.IsAssignableFrom>(actionResult.Value); + Assert.Equal(expectedTotalItems, page.Count); + Assert.Equal(pageIndex, page.PageIndex); + Assert.Equal(pageSize, page.PageSize); + Assert.Equal(expectedItemsInPage, page.Data.Count()); } - public class TestCatalogSettings : IOptionsSnapshot + private List GetFakeCatalog() { - public CatalogSettings Value => new CatalogSettings + return new List() { - PicBaseUrl = "http://image-server.com/", - AzureStorageEnabled = true + new() + { + Id = 1, + Name = "fakeItemA", + CatalogTypeId = 2, + CatalogBrandId = 1, + PictureFileName = "fakeItemA.png" + }, + new() + { + Id = 2, + Name = "fakeItemB", + CatalogTypeId = 2, + CatalogBrandId = 1, + PictureFileName = "fakeItemB.png" + }, + new() + { + Id = 3, + Name = "fakeItemC", + CatalogTypeId = 2, + CatalogBrandId = 1, + PictureFileName = "fakeItemC.png" + }, + new() + { + Id = 4, + Name = "fakeItemD", + CatalogTypeId = 2, + CatalogBrandId = 1, + PictureFileName = "fakeItemD.png" + }, + new() + { + Id = 5, + Name = "fakeItemE", + CatalogTypeId = 2, + CatalogBrandId = 1, + PictureFileName = "fakeItemE.png" + }, + new() + { + Id = 6, + Name = "fakeItemF", + CatalogTypeId = 2, + CatalogBrandId = 1, + PictureFileName = "fakeItemF.png" + } }; - - public CatalogSettings Get(string name) => Value; } +} + +public class TestCatalogSettings : IOptionsSnapshot +{ + public CatalogSettings Value => new() + { + PicBaseUrl = "http://image-server.com/", + AzureStorageEnabled = true + }; + public CatalogSettings Get(string name) => Value; } diff --git a/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj b/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj index 2bdb5ec12..513174e1d 100644 --- a/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj +++ b/src/Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj @@ -1,15 +1,15 @@  - net5.0 + net6.0 false false - + - + all diff --git a/src/Services/Identity/Identity.API/Certificate/Certificate.cs b/src/Services/Identity/Identity.API/Certificate/Certificate.cs index d20726d12..91aa74a6c 100644 --- a/src/Services/Identity/Identity.API/Certificate/Certificate.cs +++ b/src/Services/Identity/Identity.API/Certificate/Certificate.cs @@ -1,8 +1,4 @@ -using System.IO; -using System.Reflection; -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates +namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates { static class Certificate { @@ -16,24 +12,20 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates * real environment the certificate should be created and stored in a secure way, which is out * of the scope of this project. **********************************************************************************************/ - using (var stream = assembly.GetManifestResourceStream("Identity.API.Certificate.idsrv3test.pfx")) - { - return new X509Certificate2(ReadStream(stream), "idsrv3test"); - } + using var stream = assembly.GetManifestResourceStream("Identity.API.Certificate.idsrv3test.pfx"); + return new X509Certificate2(ReadStream(stream), "idsrv3test"); } private static byte[] ReadStream(Stream input) { byte[] buffer = new byte[16 * 1024]; - using (MemoryStream ms = new MemoryStream()) + using MemoryStream ms = new MemoryStream(); + int read; + while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) - { - ms.Write(buffer, 0, read); - } - return ms.ToArray(); + ms.Write(buffer, 0, read); } + return ms.ToArray(); } } } \ No newline at end of file diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs index 30f9ecb21..53d166ab7 100644 --- a/src/Services/Identity/Identity.API/Configuration/Config.cs +++ b/src/Services/Identity/Identity.API/Configuration/Config.cs @@ -1,6 +1,4 @@ -using IdentityServer4; -using IdentityServer4.Models; -using System.Collections.Generic; +using IdentityServer4.Models; namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration { @@ -8,7 +6,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration { // ApiResources define the apis in your system public static IEnumerable GetApis() - { + { return new List { new ApiResource("orders", "Orders Service"), @@ -80,7 +78,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration AllowedGrantTypes = GrantTypes.Hybrid, //Used to retrieve the access token on the back channel. ClientSecrets = - { + { new Secret("secret".Sha256()) }, RedirectUris = { clientsUrl["Xamarin"] }, @@ -108,6 +106,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration ClientName = "MVC Client", ClientSecrets = new List { + new Secret("secret".Sha256()) }, ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client diff --git a/src/Services/Identity/Identity.API/Controllers/AccountController.cs b/src/Services/Identity/Identity.API/Controllers/AccountController.cs index 60191b9f3..a4943a3ba 100644 --- a/src/Services/Identity/Identity.API/Controllers/AccountController.cs +++ b/src/Services/Identity/Identity.API/Controllers/AccountController.cs @@ -1,23 +1,4 @@ -using IdentityModel; -using IdentityServer4; -using IdentityServer4.Models; -using IdentityServer4.Services; -using IdentityServer4.Stores; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; -using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels; -using Microsoft.eShopOnContainers.Services.Identity.API.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using System; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers +namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers { /// /// This sample controller implements a typical login/logout/provision workflow for local accounts. diff --git a/src/Services/Identity/Identity.API/Controllers/HomeController.cs b/src/Services/Identity/Identity.API/Controllers/HomeController.cs index 30edd16b3..3c31c4ab1 100644 --- a/src/Services/Identity/Identity.API/Controllers/HomeController.cs +++ b/src/Services/Identity/Identity.API/Controllers/HomeController.cs @@ -1,12 +1,4 @@ - -using IdentityServer4.Services; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; -using Microsoft.eShopOnContainers.Services.Identity.API.Services; -using Microsoft.Extensions.Options; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers +namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers { public class HomeController : Controller { diff --git a/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs b/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs index aec67258c..227406008 100644 --- a/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs +++ b/src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs @@ -1,8 +1,4 @@ -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Data +namespace Microsoft.eShopOnContainers.Services.Identity.API.Data { public class ApplicationDbContext : IdentityDbContext { diff --git a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs index b80f506a9..6ee9fd499 100644 --- a/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs +++ b/src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs @@ -1,21 +1,6 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Identity; -using Microsoft.eShopOnContainers.Services.Identity.API.Extensions; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Data +namespace Microsoft.eShopOnContainers.Services.Identity.API.Data { - - + using Microsoft.Extensions.Logging; public class ApplicationDbContextSeed { private readonly IPasswordHasher _passwordHasher = new PasswordHasher(); @@ -149,7 +134,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data City = "Redmond", Country = "U.S.", Email = "demouser@microsoft.com", - Expiration = "12/21", + Expiration = "12/25", Id = Guid.NewGuid().ToString(), LastName = "DemoLastName", Name = "DemoUser", @@ -206,23 +191,21 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data string imagePath = Path.Combine(webroot, "images"); string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); - using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + using ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read); + foreach (ZipArchiveEntry entry in zip.Entries) { - foreach (ZipArchiveEntry entry in zip.Entries) + if (imageFiles.Contains(entry.Name)) { - if (imageFiles.Contains(entry.Name)) - { - string destinationFilename = Path.Combine(imagePath, entry.Name); - if (File.Exists(destinationFilename)) - { - File.Delete(destinationFilename); - } - entry.ExtractToFile(destinationFilename); - } - else + string destinationFilename = Path.Combine(imagePath, entry.Name); + if (File.Exists(destinationFilename)) { - logger.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); + File.Delete(destinationFilename); } + entry.ExtractToFile(destinationFilename); + } + else + { + logger.LogWarning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); } } } diff --git a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs index 4a0c78d88..6872fdad4 100644 --- a/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs +++ b/src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs @@ -1,12 +1,4 @@ -using IdentityServer4.EntityFramework.DbContexts; -using IdentityServer4.EntityFramework.Entities; -using IdentityServer4.EntityFramework.Mappers; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Identity.API.Configuration; -using Microsoft.Extensions.Configuration; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using IdentityServer4.EntityFramework.Entities; namespace Microsoft.eShopOnContainers.Services.Identity.API.Data { diff --git a/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs b/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs index d43a9ab15..8912882f4 100644 --- a/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs +++ b/src/Services/Identity/Identity.API/Devspaces/DevspacesRedirectUriValidator.cs @@ -1,11 +1,7 @@ -using IdentityServer4.Models; -using IdentityServer4.Validation; -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; - - namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces { + using Microsoft.Extensions.Logging; + public class DevspacesRedirectUriValidator : IRedirectUriValidator { private readonly ILogger _logger; @@ -14,14 +10,14 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces _logger = logger; } - public Task IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client) + public Task IsPostLogoutRedirectUriValidAsync(string requestedUri, IdentityServer4.Models.Client client) { _logger.LogInformation("Client {ClientName} used post logout uri {RequestedUri}.", client.ClientName, requestedUri); return Task.FromResult(true); } - public Task IsRedirectUriValidAsync(string requestedUri, Client client) + public Task IsRedirectUriValidAsync(string requestedUri, IdentityServer4.Models.Client client) { _logger.LogInformation("Client {ClientName} used post logout uri {RequestedUri}.", client.ClientName, requestedUri); return Task.FromResult(true); diff --git a/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs b/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs index 5294177c7..201c85ab2 100644 --- a/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs +++ b/src/Services/Identity/Identity.API/Devspaces/IdentityDevspacesBuilderExtensions.cs @@ -1,6 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces +namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces { static class IdentityDevspacesBuilderExtensions { diff --git a/src/Services/Identity/Identity.API/Dockerfile b/src/Services/Identity/Identity.API/Dockerfile index 3608476bc..674cc4ec1 100644 --- a/src/Services/Identity/Identity.API/Dockerfile +++ b/src/Services/Identity/Identity.API/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Identity/Identity.API/Dockerfile.develop b/src/Services/Identity/Identity.API/Dockerfile.develop index 0d50b0388..9afc17772 100644 --- a/src/Services/Identity/Identity.API/Dockerfile.develop +++ b/src/Services/Identity/Identity.API/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs b/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs index 1061881af..0e2c4c72b 100644 --- a/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs +++ b/src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Extensions +namespace Microsoft.eShopOnContainers.Services.Identity.API.Extensions { public static class LinqSelectExtensions { diff --git a/src/Services/Identity/Identity.API/Factories/ApplicationDbContextFactory.cs b/src/Services/Identity/Identity.API/Factories/ApplicationDbContextFactory.cs index bb3f7bfe2..c1fb0198c 100644 --- a/src/Services/Identity/Identity.API/Factories/ApplicationDbContextFactory.cs +++ b/src/Services/Identity/Identity.API/Factories/ApplicationDbContextFactory.cs @@ -1,10 +1,4 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.eShopOnContainers.Services.Identity.API.Data; -using Microsoft.Extensions.Configuration; -using System.IO; - -namespace Identity.API.Factories +namespace Identity.API.Factories { public class ApplicationDbContextFactory : IDesignTimeDbContextFactory { diff --git a/src/Services/Identity/Identity.API/Factories/ConfigurationDbContextFactory.cs b/src/Services/Identity/Identity.API/Factories/ConfigurationDbContextFactory.cs index e304f50a8..0fdbe8598 100644 --- a/src/Services/Identity/Identity.API/Factories/ConfigurationDbContextFactory.cs +++ b/src/Services/Identity/Identity.API/Factories/ConfigurationDbContextFactory.cs @@ -1,11 +1,4 @@ -using IdentityServer4.EntityFramework.DbContexts; -using IdentityServer4.EntityFramework.Options; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; -using System.IO; - -namespace Identity.API.Factories +namespace Identity.API.Factories { public class ConfigurationDbContextFactory : IDesignTimeDbContextFactory { diff --git a/src/Services/Identity/Identity.API/Factories/PersistedGrantDbContextFactory.cs b/src/Services/Identity/Identity.API/Factories/PersistedGrantDbContextFactory.cs index b3dff8d9a..83380dfd0 100644 --- a/src/Services/Identity/Identity.API/Factories/PersistedGrantDbContextFactory.cs +++ b/src/Services/Identity/Identity.API/Factories/PersistedGrantDbContextFactory.cs @@ -1,11 +1,4 @@ -using IdentityServer4.EntityFramework.DbContexts; -using IdentityServer4.EntityFramework.Options; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; -using System.IO; - -namespace Identity.API.Factories +namespace Identity.API.Factories { public class PersistedGrantDbContextFactory : IDesignTimeDbContextFactory { diff --git a/src/Services/Identity/Identity.API/GlobalUsings.cs b/src/Services/Identity/Identity.API/GlobalUsings.cs new file mode 100644 index 000000000..bfbb354db --- /dev/null +++ b/src/Services/Identity/Identity.API/GlobalUsings.cs @@ -0,0 +1,183 @@ +global using Microsoft.eShopOnContainers.Services.Identity.API.Extensions; +global using System.IO.Compression; +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using Azure.Core; +global using Azure.Identity; +global using HealthChecks.UI.Client; +global using IdentityModel; +global using IdentityServer4.EntityFramework.DbContexts; +global using IdentityServer4.EntityFramework.Mappers; +global using IdentityServer4.EntityFramework.Options; +global using IdentityServer4.Models; +global using IdentityServer4.Services; +global using IdentityServer4.Stores; +global using IdentityServer4.Validation; +global using IdentityServer4; +global using Microsoft.AspNetCore.Authentication; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +global using Microsoft.AspNetCore.Identity; +global using Microsoft.AspNetCore.Mvc.Rendering; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore; +global using Microsoft.EntityFrameworkCore.Design; +global using Microsoft.EntityFrameworkCore.Infrastructure; +global using Microsoft.EntityFrameworkCore.Metadata; +global using Microsoft.EntityFrameworkCore.Migrations; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.eShopOnContainers.Services.Identity.API.Certificates; +global using Microsoft.eShopOnContainers.Services.Identity.API.Configuration; +global using Microsoft.eShopOnContainers.Services.Identity.API.Data; +global using Microsoft.eShopOnContainers.Services.Identity.API.Devspaces; +global using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels; +global using Microsoft.eShopOnContainers.Services.Identity.API.Models; +global using Microsoft.eShopOnContainers.Services.Identity.API.Services; +global using Microsoft.eShopOnContainers.Services.Identity.API; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Polly; +global using Serilog; +global using StackExchange.Redis; +global using System.Collections.Generic; +global using System.ComponentModel.DataAnnotations; +global using System.Data.SqlClient; +global using System.IdentityModel.Tokens.Jwt; +global using System.IO; +global using System.Linq; +global using System.Reflection; +global using System.Security.Claims; +global using System.Security.Cryptography.X509Certificates; +global using System.Text.RegularExpressions; +global using System.Threading.Tasks; +global using System; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/IWebHostExtensions.cs b/src/Services/Identity/Identity.API/IWebHostExtensions.cs index aff262b73..57c386559 100644 --- a/src/Services/Identity/Identity.API/IWebHostExtensions.cs +++ b/src/Services/Identity/Identity.API/IWebHostExtensions.cs @@ -1,11 +1,3 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Polly; -using System; -using System.Data.SqlClient; - namespace Microsoft.AspNetCore.Hosting { public static class IWebHostExtensions @@ -21,52 +13,50 @@ namespace Microsoft.AspNetCore.Hosting { var underK8s = webHost.IsInKubernetes(); - using (var scope = webHost.Services.CreateScope()) + using var scope = webHost.Services.CreateScope(); + var services = scope.ServiceProvider; + var logger = services.GetRequiredService>(); + var context = services.GetService(); + + try { - var services = scope.ServiceProvider; - var logger = services.GetRequiredService>(); - var context = services.GetService(); + logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - try + if (underK8s) { - logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); - - if (underK8s) - { - InvokeSeeder(seeder, context, services); - } - else - { - var retries = 10; - var retry = Policy.Handle() - .WaitAndRetry( - retryCount: retries, - sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); - }); - - //if the sql server container is not created on run docker compose this - //migration can't fail for network related exception. The retry options for DbContext only - //apply to transient exceptions - // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) - retry.Execute(() => InvokeSeeder(seeder, context, services)); - } + InvokeSeeder(seeder, context, services); + } + else + { + var retries = 10; + var retry = Policy.Handle() + .WaitAndRetry( + retryCount: retries, + sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), + onRetry: (exception, timeSpan, retry, ctx) => + { + logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", nameof(TContext), exception.GetType().Name, exception.Message, retry, retries); + }); - logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + //if the sql server container is not created on run docker compose this + //migration can't fail for network related exception. The retry options for DbContext only + //apply to transient exceptions + // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + retry.Execute(() => InvokeSeeder(seeder, context, services)); } - catch (Exception ex) + + logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + if (underK8s) { - logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); - if (underK8s) - { - throw; // Rethrow under k8s because we rely on k8s to re-run the pod - } + throw; // Rethrow under k8s because we rely on k8s to re-run the pod } } - return webHost; + return webHost; } private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj index 4ea6237b6..51e2316be 100644 --- a/src/Services/Identity/Identity.API/Identity.API.csproj +++ b/src/Services/Identity/Identity.API/Identity.API.csproj @@ -1,12 +1,11 @@  - net5.0 + net6.0 aspnet-eShopOnContainers.Identity-90487118-103c-4ff0-b9da-e5e26f7ab0c5 ..\..\..\..\docker-compose.dcproj false - true - preview + true @@ -16,44 +15,38 @@ - + - - - - - - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + + - - - - - - - - - + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/Migrations/20190729091724_InitialMigration.Designer.cs b/src/Services/Identity/Identity.API/Migrations/20210813072445_InitialMigration.Designer.cs similarity index 54% rename from src/Services/Identity/Identity.API/Migrations/20190729091724_InitialMigration.Designer.cs rename to src/Services/Identity/Identity.API/Migrations/20210813072445_InitialMigration.Designer.cs index 5ad802992..b6c43abf5 100644 --- a/src/Services/Identity/Identity.API/Migrations/20190729091724_InitialMigration.Designer.cs +++ b/src/Services/Identity/Identity.API/Migrations/20210813072445_InitialMigration.Designer.cs @@ -10,209 +10,258 @@ using Microsoft.eShopOnContainers.Services.Identity.API.Data; namespace Identity.API.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190729091724_InitialMigration")] + [Migration("20210813072445_InitialMigration")] partial class InitialMigration { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6") .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "6.0.0") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { - b.Property("Id"); + b.Property("Id") + .HasColumnType("nvarchar(450)"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); b.Property("Name") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() - .HasName("RoleNameIndex") + .HasDatabaseName("RoleNameIndex") .HasFilter("[NormalizedName] IS NOT NULL"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() + .HasColumnType("int") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); b.Property("RoleId") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(450)"); b.HasKey("Id"); b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() + .HasColumnType("int") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(450)"); b.HasKey("Id"); b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); - b.Property("ProviderKey"); + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); - b.Property("ProviderDisplayName"); + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(450)"); b.HasKey("LoginProvider", "ProviderKey"); b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("nvarchar(450)"); - b.Property("RoleId"); + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); b.HasKey("UserId", "RoleId"); b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("nvarchar(450)"); - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); - b.Property("Name"); + b.Property("Name") + .HasColumnType("nvarchar(450)"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("nvarchar(max)"); b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Identity.API.Models.ApplicationUser", b => { - b.Property("Id"); + b.Property("Id") + .HasColumnType("nvarchar(450)"); - b.Property("AccessFailedCount"); + b.Property("AccessFailedCount") + .HasColumnType("int"); b.Property("CardHolderName") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("CardNumber") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("CardType"); + b.Property("CardType") + .HasColumnType("int"); b.Property("City") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); b.Property("Country") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); - b.Property("EmailConfirmed"); + b.Property("EmailConfirmed") + .HasColumnType("bit"); b.Property("Expiration") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("LastName") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("LockoutEnabled"); + b.Property("LockoutEnabled") + .HasColumnType("bit"); - b.Property("LockoutEnd"); + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); b.Property("Name") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("NormalizedEmail") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedUserName") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); - b.Property("PasswordHash"); + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); - b.Property("PhoneNumber"); + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); - b.Property("PhoneNumberConfirmed"); + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); b.Property("SecurityNumber") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("SecurityStamp"); + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); b.Property("State") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("Street") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("TwoFactorEnabled"); + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); b.Property("UserName") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ZipCode") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); + .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() - .HasName("UserNameIndex") + .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => diff --git a/src/Services/Identity/Identity.API/Migrations/20190729091724_InitialMigration.cs b/src/Services/Identity/Identity.API/Migrations/20210813072445_InitialMigration.cs similarity index 57% rename from src/Services/Identity/Identity.API/Migrations/20190729091724_InitialMigration.cs rename to src/Services/Identity/Identity.API/Migrations/20210813072445_InitialMigration.cs index 58c80842b..88587a677 100644 --- a/src/Services/Identity/Identity.API/Migrations/20190729091724_InitialMigration.cs +++ b/src/Services/Identity/Identity.API/Migrations/20210813072445_InitialMigration.cs @@ -1,6 +1,5 @@ -using Microsoft.EntityFrameworkCore.Metadata; +using System; using Microsoft.EntityFrameworkCore.Migrations; -using System; namespace Identity.API.Migrations { @@ -12,10 +11,10 @@ namespace Identity.API.Migrations name: "AspNetRoles", columns: table => new { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 256, nullable: true), - NormalizedName = table.Column(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(nullable: true) + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -26,33 +25,33 @@ namespace Identity.API.Migrations name: "AspNetUsers", columns: table => new { - Id = table.Column(nullable: false), - UserName = table.Column(maxLength: 256, nullable: true), - NormalizedUserName = table.Column(maxLength: 256, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false), - PasswordHash = table.Column(nullable: true), - SecurityStamp = table.Column(nullable: true), - ConcurrencyStamp = table.Column(nullable: true), - PhoneNumber = table.Column(nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false), - TwoFactorEnabled = table.Column(nullable: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false), - AccessFailedCount = table.Column(nullable: false), - CardNumber = table.Column(nullable: false), - SecurityNumber = table.Column(nullable: false), - Expiration = table.Column(nullable: false), - CardHolderName = table.Column(nullable: false), - CardType = table.Column(nullable: false), - Street = table.Column(nullable: false), - City = table.Column(nullable: false), - State = table.Column(nullable: false), - Country = table.Column(nullable: false), - ZipCode = table.Column(nullable: false), - Name = table.Column(nullable: false), - LastName = table.Column(nullable: false) + Id = table.Column(type: "nvarchar(450)", nullable: false), + CardNumber = table.Column(type: "nvarchar(max)", nullable: false), + SecurityNumber = table.Column(type: "nvarchar(max)", nullable: false), + Expiration = table.Column(type: "nvarchar(max)", nullable: false), + CardHolderName = table.Column(type: "nvarchar(max)", nullable: false), + CardType = table.Column(type: "int", nullable: false), + Street = table.Column(type: "nvarchar(max)", nullable: false), + City = table.Column(type: "nvarchar(max)", nullable: false), + State = table.Column(type: "nvarchar(max)", nullable: false), + Country = table.Column(type: "nvarchar(max)", nullable: false), + ZipCode = table.Column(type: "nvarchar(max)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + LastName = table.Column(type: "nvarchar(max)", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) }, constraints: table => { @@ -63,11 +62,11 @@ namespace Identity.API.Migrations name: "AspNetRoleClaims", columns: table => new { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - RoleId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -84,11 +83,11 @@ namespace Identity.API.Migrations name: "AspNetUserClaims", columns: table => new { - Id = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - UserId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -105,10 +104,10 @@ namespace Identity.API.Migrations name: "AspNetUserLogins", columns: table => new { - LoginProvider = table.Column(nullable: false), - ProviderKey = table.Column(nullable: false), - ProviderDisplayName = table.Column(nullable: true), - UserId = table.Column(nullable: false) + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) }, constraints: table => { @@ -125,8 +124,8 @@ namespace Identity.API.Migrations name: "AspNetUserRoles", columns: table => new { - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) }, constraints: table => { @@ -149,10 +148,10 @@ namespace Identity.API.Migrations name: "AspNetUserTokens", columns: table => new { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(nullable: false), - Name = table.Column(nullable: false), - Value = table.Column(nullable: true) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { diff --git a/src/Services/Identity/Identity.API/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Services/Identity/Identity.API/Migrations/ApplicationDbContextModelSnapshot.cs index 2819cd6eb..0076eb5bf 100644 --- a/src/Services/Identity/Identity.API/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Services/Identity/Identity.API/Migrations/ApplicationDbContextModelSnapshot.cs @@ -15,202 +15,251 @@ namespace Identity.API.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6") .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "6.0.0") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { - b.Property("Id"); + b.Property("Id") + .HasColumnType("nvarchar(450)"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); b.Property("Name") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() - .HasName("RoleNameIndex") + .HasDatabaseName("RoleNameIndex") .HasFilter("[NormalizedName] IS NOT NULL"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() + .HasColumnType("int") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); b.Property("RoleId") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(450)"); b.HasKey("Id"); b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() + .HasColumnType("int") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ClaimType"); + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); - b.Property("ClaimValue"); + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(450)"); b.HasKey("Id"); b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); - b.Property("ProviderKey"); + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); - b.Property("ProviderDisplayName"); + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); b.Property("UserId") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(450)"); b.HasKey("LoginProvider", "ProviderKey"); b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("nvarchar(450)"); - b.Property("RoleId"); + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); b.HasKey("UserId", "RoleId"); b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.Property("UserId"); + b.Property("UserId") + .HasColumnType("nvarchar(450)"); - b.Property("LoginProvider"); + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); - b.Property("Name"); + b.Property("Name") + .HasColumnType("nvarchar(450)"); - b.Property("Value"); + b.Property("Value") + .HasColumnType("nvarchar(max)"); b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Identity.API.Models.ApplicationUser", b => { - b.Property("Id"); + b.Property("Id") + .HasColumnType("nvarchar(450)"); - b.Property("AccessFailedCount"); + b.Property("AccessFailedCount") + .HasColumnType("int"); b.Property("CardHolderName") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("CardNumber") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("CardType"); + b.Property("CardType") + .HasColumnType("int"); b.Property("City") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); b.Property("Country") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); - b.Property("EmailConfirmed"); + b.Property("EmailConfirmed") + .HasColumnType("bit"); b.Property("Expiration") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("LastName") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("LockoutEnabled"); + b.Property("LockoutEnabled") + .HasColumnType("bit"); - b.Property("LockoutEnd"); + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); b.Property("Name") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("NormalizedEmail") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedUserName") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); - b.Property("PasswordHash"); + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); - b.Property("PhoneNumber"); + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); - b.Property("PhoneNumberConfirmed"); + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); b.Property("SecurityNumber") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("SecurityStamp"); + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); b.Property("State") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.Property("Street") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("TwoFactorEnabled"); + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); b.Property("UserName") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("ZipCode") - .IsRequired(); + .IsRequired() + .HasColumnType("nvarchar(max)"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); + .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() - .HasName("UserNameIndex") + .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20210813072543_InitialMigration.Designer.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20210813072543_InitialMigration.Designer.cs new file mode 100644 index 000000000..c5e7b3457 --- /dev/null +++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20210813072543_InitialMigration.Designer.cs @@ -0,0 +1,911 @@ +// +using System; +using IdentityServer4.EntityFramework.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Identity.API.Migrations.ConfigurationDb +{ + [DbContext(typeof(ConfigurationDbContext))] + [Migration("20210813072543_InitialMigration")] + partial class InitialMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("NonEditable") + .HasColumnType("bit"); + + b.Property("Updated") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("ApiResources", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ApiResourceId") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ApiResourceId"); + + b.ToTable("ApiClaims", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ApiResourceId") + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("Id"); + + b.HasIndex("ApiResourceId"); + + b.ToTable("ApiProperties", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ApiResourceId") + .HasColumnType("int"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("ApiResourceId"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("ApiScopes", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ApiScopeId") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ApiScopeId"); + + b.ToTable("ApiScopeClaims", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ApiResourceId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.HasKey("Id"); + + b.HasIndex("ApiResourceId"); + + b.ToTable("ApiSecrets", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("AbsoluteRefreshTokenLifetime") + .HasColumnType("int"); + + b.Property("AccessTokenLifetime") + .HasColumnType("int"); + + b.Property("AccessTokenType") + .HasColumnType("int"); + + b.Property("AllowAccessTokensViaBrowser") + .HasColumnType("bit"); + + b.Property("AllowOfflineAccess") + .HasColumnType("bit"); + + b.Property("AllowPlainTextPkce") + .HasColumnType("bit"); + + b.Property("AllowRememberConsent") + .HasColumnType("bit"); + + b.Property("AlwaysIncludeUserClaimsInIdToken") + .HasColumnType("bit"); + + b.Property("AlwaysSendClientClaims") + .HasColumnType("bit"); + + b.Property("AuthorizationCodeLifetime") + .HasColumnType("int"); + + b.Property("BackChannelLogoutSessionRequired") + .HasColumnType("bit"); + + b.Property("BackChannelLogoutUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("ConsentLifetime") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DeviceCodeLifetime") + .HasColumnType("int"); + + b.Property("EnableLocalLogin") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("FrontChannelLogoutSessionRequired") + .HasColumnType("bit"); + + b.Property("FrontChannelLogoutUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("IdentityTokenLifetime") + .HasColumnType("int"); + + b.Property("IncludeJwtId") + .HasColumnType("bit"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("LogoUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("NonEditable") + .HasColumnType("bit"); + + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ProtocolType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("RefreshTokenExpiration") + .HasColumnType("int"); + + b.Property("RefreshTokenUsage") + .HasColumnType("int"); + + b.Property("RequireClientSecret") + .HasColumnType("bit"); + + b.Property("RequireConsent") + .HasColumnType("bit"); + + b.Property("RequirePkce") + .HasColumnType("bit"); + + b.Property("SlidingRefreshTokenLifetime") + .HasColumnType("int"); + + b.Property("UpdateAccessTokenClaimsOnRefresh") + .HasColumnType("bit"); + + b.Property("Updated") + .HasColumnType("datetime2"); + + b.Property("UserCodeType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UserSsoLifetime") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ClientId") + .IsUnique(); + + b.ToTable("Clients", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientClaims", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Origin") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientCorsOrigins", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("GrantType") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientGrantTypes", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Provider") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientIdPRestrictions", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("PostLogoutRedirectUri") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientPostLogoutRedirectUris", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientProperties", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("RedirectUri") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientRedirectUris", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Scope") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientScopes", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("ClientId") + .HasColumnType("int"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("ClientSecrets", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("IdentityResourceId") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("IdentityResourceId"); + + b.ToTable("IdentityClaims", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("NonEditable") + .HasColumnType("bit"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.Property("Updated") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("IdentityResources", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + b.Property("IdentityResourceId") + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("Id"); + + b.HasIndex("IdentityResourceId"); + + b.ToTable("IdentityProperties", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApiResource"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + .WithMany("Properties") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApiResource"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + .WithMany("Scopes") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApiResource"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.ApiScope", "ApiScope") + .WithMany("UserClaims") + .HasForeignKey("ApiScopeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApiScope"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.ApiResource", "ApiResource") + .WithMany("Secrets") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ApiResource"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("Claims") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("AllowedCorsOrigins") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("AllowedGrantTypes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("IdentityProviderRestrictions") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("PostLogoutRedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("Properties") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("RedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("AllowedScopes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.Client", "Client") + .WithMany("ClientSecrets") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") + .WithMany("UserClaims") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("IdentityResource"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b => + { + b.HasOne("IdentityServer4.EntityFramework.Entities.IdentityResource", "IdentityResource") + .WithMany("Properties") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("IdentityResource"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => + { + b.Navigation("Properties"); + + b.Navigation("Scopes"); + + b.Navigation("Secrets"); + + b.Navigation("UserClaims"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b => + { + b.Navigation("UserClaims"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b => + { + b.Navigation("AllowedCorsOrigins"); + + b.Navigation("AllowedGrantTypes"); + + b.Navigation("AllowedScopes"); + + b.Navigation("Claims"); + + b.Navigation("ClientSecrets"); + + b.Navigation("IdentityProviderRestrictions"); + + b.Navigation("PostLogoutRedirectUris"); + + b.Navigation("Properties"); + + b.Navigation("RedirectUris"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => + { + b.Navigation("Properties"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20210813072543_InitialMigration.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20210813072543_InitialMigration.cs new file mode 100644 index 000000000..57f508711 --- /dev/null +++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/20210813072543_InitialMigration.cs @@ -0,0 +1,607 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Identity.API.Migrations.ConfigurationDb +{ + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApiResources", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + Updated = table.Column(type: "datetime2", nullable: true), + LastAccessed = table.Column(type: "datetime2", nullable: true), + NonEditable = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Clients", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ProtocolType = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + RequireClientSecret = table.Column(type: "bit", nullable: false), + ClientName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + ClientUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + LogoUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + RequireConsent = table.Column(type: "bit", nullable: false), + AllowRememberConsent = table.Column(type: "bit", nullable: false), + AlwaysIncludeUserClaimsInIdToken = table.Column(type: "bit", nullable: false), + RequirePkce = table.Column(type: "bit", nullable: false), + AllowPlainTextPkce = table.Column(type: "bit", nullable: false), + AllowAccessTokensViaBrowser = table.Column(type: "bit", nullable: false), + FrontChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + FrontChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), + BackChannelLogoutUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + BackChannelLogoutSessionRequired = table.Column(type: "bit", nullable: false), + AllowOfflineAccess = table.Column(type: "bit", nullable: false), + IdentityTokenLifetime = table.Column(type: "int", nullable: false), + AccessTokenLifetime = table.Column(type: "int", nullable: false), + AuthorizationCodeLifetime = table.Column(type: "int", nullable: false), + ConsentLifetime = table.Column(type: "int", nullable: true), + AbsoluteRefreshTokenLifetime = table.Column(type: "int", nullable: false), + SlidingRefreshTokenLifetime = table.Column(type: "int", nullable: false), + RefreshTokenUsage = table.Column(type: "int", nullable: false), + UpdateAccessTokenClaimsOnRefresh = table.Column(type: "bit", nullable: false), + RefreshTokenExpiration = table.Column(type: "int", nullable: false), + AccessTokenType = table.Column(type: "int", nullable: false), + EnableLocalLogin = table.Column(type: "bit", nullable: false), + IncludeJwtId = table.Column(type: "bit", nullable: false), + AlwaysSendClientClaims = table.Column(type: "bit", nullable: false), + ClientClaimsPrefix = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + PairWiseSubjectSalt = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Created = table.Column(type: "datetime2", nullable: false), + Updated = table.Column(type: "datetime2", nullable: true), + LastAccessed = table.Column(type: "datetime2", nullable: true), + UserSsoLifetime = table.Column(type: "int", nullable: true), + UserCodeType = table.Column(type: "nvarchar(100)", maxLength: 100, nullable: true), + DeviceCodeLifetime = table.Column(type: "int", nullable: false), + NonEditable = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Clients", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityResources", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Enabled = table.Column(type: "bit", nullable: false), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Required = table.Column(type: "bit", nullable: false), + Emphasize = table.Column(type: "bit", nullable: false), + ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false), + Created = table.Column(type: "datetime2", nullable: false), + Updated = table.Column(type: "datetime2", nullable: true), + NonEditable = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityResources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ApiClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiResourceId = table.Column(type: "int", nullable: false), + Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiClaims", x => x.Id); + table.ForeignKey( + name: "FK_ApiClaims_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiResourceId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiProperties", x => x.Id); + table.ForeignKey( + name: "FK_ApiProperties_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiScopes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DisplayName = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Required = table.Column(type: "bit", nullable: false), + Emphasize = table.Column(type: "bit", nullable: false), + ShowInDiscoveryDocument = table.Column(type: "bit", nullable: false), + ApiResourceId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiScopes", x => x.Id); + table.ForeignKey( + name: "FK_ApiScopes_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiSecrets", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiResourceId = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: true), + Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Created = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiSecrets", x => x.Id); + table.ForeignKey( + name: "FK_ApiSecrets_ApiResources_ApiResourceId", + column: x => x.ApiResourceId, + principalTable: "ApiResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientClaims", x => x.Id); + table.ForeignKey( + name: "FK_ClientClaims_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientCorsOrigins", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Origin = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientCorsOrigins", x => x.Id); + table.ForeignKey( + name: "FK_ClientCorsOrigins_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientGrantTypes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + GrantType = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientGrantTypes", x => x.Id); + table.ForeignKey( + name: "FK_ClientGrantTypes_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientIdPRestrictions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Provider = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientIdPRestrictions", x => x.Id); + table.ForeignKey( + name: "FK_ClientIdPRestrictions_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientPostLogoutRedirectUris", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + PostLogoutRedirectUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientPostLogoutRedirectUris", x => x.Id); + table.ForeignKey( + name: "FK_ClientPostLogoutRedirectUris_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ClientId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientProperties", x => x.Id); + table.ForeignKey( + name: "FK_ClientProperties_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientRedirectUris", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RedirectUri = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientRedirectUris", x => x.Id); + table.ForeignKey( + name: "FK_ClientRedirectUris_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientScopes", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Scope = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + ClientId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientScopes", x => x.Id); + table.ForeignKey( + name: "FK_ClientScopes_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ClientSecrets", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ClientId = table.Column(type: "int", nullable: false), + Description = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: true), + Value = table.Column(type: "nvarchar(4000)", maxLength: 4000, nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + Type = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Created = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ClientSecrets", x => x.Id); + table.ForeignKey( + name: "FK_ClientSecrets_Clients_ClientId", + column: x => x.ClientId, + principalTable: "Clients", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IdentityResourceId = table.Column(type: "int", nullable: false), + Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityClaims", x => x.Id); + table.ForeignKey( + name: "FK_IdentityClaims_IdentityResources_IdentityResourceId", + column: x => x.IdentityResourceId, + principalTable: "IdentityResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "IdentityProperties", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + IdentityResourceId = table.Column(type: "int", nullable: false), + Key = table.Column(type: "nvarchar(250)", maxLength: 250, nullable: false), + Value = table.Column(type: "nvarchar(2000)", maxLength: 2000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityProperties", x => x.Id); + table.ForeignKey( + name: "FK_IdentityProperties_IdentityResources_IdentityResourceId", + column: x => x.IdentityResourceId, + principalTable: "IdentityResources", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ApiScopeClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ApiScopeId = table.Column(type: "int", nullable: false), + Type = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiScopeClaims", x => x.Id); + table.ForeignKey( + name: "FK_ApiScopeClaims_ApiScopes_ApiScopeId", + column: x => x.ApiScopeId, + principalTable: "ApiScopes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApiClaims_ApiResourceId", + table: "ApiClaims", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiProperties_ApiResourceId", + table: "ApiProperties", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiResources_Name", + table: "ApiResources", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ApiScopeClaims_ApiScopeId", + table: "ApiScopeClaims", + column: "ApiScopeId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiScopes_ApiResourceId", + table: "ApiScopes", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiScopes_Name", + table: "ApiScopes", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ApiSecrets_ApiResourceId", + table: "ApiSecrets", + column: "ApiResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientClaims_ClientId", + table: "ClientClaims", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientCorsOrigins_ClientId", + table: "ClientCorsOrigins", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientGrantTypes_ClientId", + table: "ClientGrantTypes", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientIdPRestrictions_ClientId", + table: "ClientIdPRestrictions", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientPostLogoutRedirectUris_ClientId", + table: "ClientPostLogoutRedirectUris", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientProperties_ClientId", + table: "ClientProperties", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientRedirectUris_ClientId", + table: "ClientRedirectUris", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_Clients_ClientId", + table: "Clients", + column: "ClientId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ClientScopes_ClientId", + table: "ClientScopes", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_ClientSecrets_ClientId", + table: "ClientSecrets", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityClaims_IdentityResourceId", + table: "IdentityClaims", + column: "IdentityResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityProperties_IdentityResourceId", + table: "IdentityProperties", + column: "IdentityResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_IdentityResources_Name", + table: "IdentityResources", + column: "Name", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ApiClaims"); + + migrationBuilder.DropTable( + name: "ApiProperties"); + + migrationBuilder.DropTable( + name: "ApiScopeClaims"); + + migrationBuilder.DropTable( + name: "ApiSecrets"); + + migrationBuilder.DropTable( + name: "ClientClaims"); + + migrationBuilder.DropTable( + name: "ClientCorsOrigins"); + + migrationBuilder.DropTable( + name: "ClientGrantTypes"); + + migrationBuilder.DropTable( + name: "ClientIdPRestrictions"); + + migrationBuilder.DropTable( + name: "ClientPostLogoutRedirectUris"); + + migrationBuilder.DropTable( + name: "ClientProperties"); + + migrationBuilder.DropTable( + name: "ClientRedirectUris"); + + migrationBuilder.DropTable( + name: "ClientScopes"); + + migrationBuilder.DropTable( + name: "ClientSecrets"); + + migrationBuilder.DropTable( + name: "IdentityClaims"); + + migrationBuilder.DropTable( + name: "IdentityProperties"); + + migrationBuilder.DropTable( + name: "ApiScopes"); + + migrationBuilder.DropTable( + name: "Clients"); + + migrationBuilder.DropTable( + name: "IdentityResources"); + + migrationBuilder.DropTable( + name: "ApiResources"); + } + } +} diff --git a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs index be6b16490..662fb0f9f 100644 --- a/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs +++ b/src/Services/Identity/Identity.API/Migrations/ConfigurationDb/ConfigurationDbContextModelSnapshot.cs @@ -15,16 +15,16 @@ namespace Identity.API.Migrations.ConfigurationDb { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AllowedAccessTokenSigningAlgorithms") .HasMaxLength(100) @@ -66,7 +66,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("Name") .IsUnique(); - b.ToTable("ApiResources"); + b.ToTable("ApiResources", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b => @@ -74,7 +74,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -96,7 +96,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -123,7 +123,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ApiResourceId") .HasColumnType("int"); @@ -214,7 +214,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("Name") .IsUnique(); - b.ToTable("ApiScopes"); + b.ToTable("ApiScopes", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b => @@ -222,7 +222,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ScopeId") .HasColumnType("int"); @@ -236,7 +236,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ScopeId"); - b.ToTable("ApiScopeClaims"); + b.ToTable("ApiScopeClaims", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeProperty", b => @@ -244,7 +244,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Key") .IsRequired() @@ -271,7 +271,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("AbsoluteRefreshTokenLifetime") .HasColumnType("int"); @@ -421,7 +421,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId") .IsUnique(); - b.ToTable("Clients"); + b.ToTable("Clients", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b => @@ -429,7 +429,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -448,7 +448,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientClaims"); + b.ToTable("ClientClaims", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b => @@ -456,7 +456,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -470,7 +470,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientCorsOrigins"); + b.ToTable("ClientCorsOrigins", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b => @@ -478,7 +478,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -492,7 +492,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientGrantTypes"); + b.ToTable("ClientGrantTypes", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b => @@ -500,7 +500,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -514,7 +514,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientIdPRestrictions"); + b.ToTable("ClientIdPRestrictions", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b => @@ -522,7 +522,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -536,7 +536,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientPostLogoutRedirectUris"); + b.ToTable("ClientPostLogoutRedirectUris", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b => @@ -544,7 +544,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -563,7 +563,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientProperties"); + b.ToTable("ClientProperties", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b => @@ -571,7 +571,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -585,7 +585,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientRedirectUris"); + b.ToTable("ClientRedirectUris", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b => @@ -593,7 +593,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -607,7 +607,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientScopes"); + b.ToTable("ClientScopes", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b => @@ -615,7 +615,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("ClientId") .HasColumnType("int"); @@ -644,7 +644,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("ClientId"); - b.ToTable("ClientSecrets"); + b.ToTable("ClientSecrets", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b => @@ -652,7 +652,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Created") .HasColumnType("datetime2"); @@ -693,7 +693,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.HasIndex("Name") .IsUnique(); - b.ToTable("IdentityResources"); + b.ToTable("IdentityResources", (string)null); }); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceClaim", b => @@ -723,7 +723,7 @@ namespace Identity.API.Migrations.ConfigurationDb b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int") - .UseIdentityColumn(); + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("IdentityResourceId") .HasColumnType("int"); diff --git a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20210813072513_InitialMigration.Designer.cs b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20210813072513_InitialMigration.Designer.cs new file mode 100644 index 000000000..6e2567b4a --- /dev/null +++ b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20210813072513_InitialMigration.Designer.cs @@ -0,0 +1,108 @@ +// +using System; +using IdentityServer4.EntityFramework.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Identity.API.Migrations.PersistedGrantDb +{ + [DbContext(typeof(PersistedGrantDbContext))] + [Migration("20210813072513_InitialMigration")] + partial class InitialMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => + { + b.Property("UserCode") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(50000) + .HasColumnType("nvarchar(max)"); + + b.Property("DeviceCode") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("datetime2"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("UserCode"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.ToTable("DeviceCodes", (string)null); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(50000) + .HasColumnType("nvarchar(max)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Key"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("PersistedGrants", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20210813072513_InitialMigration.cs b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20210813072513_InitialMigration.cs new file mode 100644 index 000000000..e81f8a197 --- /dev/null +++ b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/20210813072513_InitialMigration.cs @@ -0,0 +1,75 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Identity.API.Migrations.PersistedGrantDb +{ + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "DeviceCodes", + columns: table => new + { + UserCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + DeviceCode = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + Expiration = table.Column(type: "datetime2", nullable: false), + Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); + }); + + migrationBuilder.CreateTable( + name: "PersistedGrants", + columns: table => new + { + Key = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + Type = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + SubjectId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + ClientId = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + Expiration = table.Column(type: "datetime2", nullable: true), + Data = table.Column(type: "nvarchar(max)", maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedGrants", x => x.Key); + }); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_DeviceCode", + table: "DeviceCodes", + column: "DeviceCode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_Expiration", + table: "DeviceCodes", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_Expiration", + table: "PersistedGrants", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_ClientId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "ClientId", "Type" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DeviceCodes"); + + migrationBuilder.DropTable( + name: "PersistedGrants"); + } + } +} diff --git a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs index e79423df8..0aef40db0 100644 --- a/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs +++ b/src/Services/Identity/Identity.API/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs @@ -15,9 +15,9 @@ namespace Identity.API.Migrations.PersistedGrantDb { #pragma warning disable 612, 618 modelBuilder - .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("ProductVersion", "5.0.2"); + .HasAnnotation("ProductVersion", "6.0.0") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentInputModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentInputModel.cs index 739d833aa..fd4e524cf 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentInputModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentInputModel.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record ConsentInputModel { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/ForgotPasswordViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/ForgotPasswordViewModel.cs index ad661c65f..6cade4c6e 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/ForgotPasswordViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/ForgotPasswordViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record ForgotPasswordViewModel { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/LoginViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/LoginViewModel.cs index 97ef19aba..15fedcca6 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/LoginViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/LoginViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record LoginViewModel { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/RegisterViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/RegisterViewModel.cs index 00fc05d4b..652df6fc7 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/RegisterViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/RegisterViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record RegisterViewModel { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/ResetPasswordViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/ResetPasswordViewModel.cs index 50c5b585f..9aad9104d 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/ResetPasswordViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/ResetPasswordViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record ResetPasswordViewModel { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/SendCodeViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/SendCodeViewModel.cs index 35429e9e5..207d34ba9 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/SendCodeViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/SendCodeViewModel.cs @@ -1,7 +1,4 @@ -using Microsoft.AspNetCore.Mvc.Rendering; -using System.Collections.Generic; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record SendCodeViewModel { diff --git a/src/Services/Identity/Identity.API/Models/AccountViewModels/VerifyCodeViewModel.cs b/src/Services/Identity/Identity.API/Models/AccountViewModels/VerifyCodeViewModel.cs index e54d6c05b..d4c15e605 100644 --- a/src/Services/Identity/Identity.API/Models/AccountViewModels/VerifyCodeViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/AccountViewModels/VerifyCodeViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels { public record VerifyCodeViewModel { diff --git a/src/Services/Identity/Identity.API/Models/ApplicationUser.cs b/src/Services/Identity/Identity.API/Models/ApplicationUser.cs index fa43017fc..ee5e8d089 100644 --- a/src/Services/Identity/Identity.API/Models/ApplicationUser.cs +++ b/src/Services/Identity/Identity.API/Models/ApplicationUser.cs @@ -1,7 +1,4 @@ -using Microsoft.AspNetCore.Identity; -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models { // Add profile data for application users by adding properties to the ApplicationUser class public class ApplicationUser : IdentityUser diff --git a/src/Services/Identity/Identity.API/Models/ErrorViewModel.cs b/src/Services/Identity/Identity.API/Models/ErrorViewModel.cs index a327e7b08..5076b6c1c 100644 --- a/src/Services/Identity/Identity.API/Models/ErrorViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ErrorViewModel.cs @@ -1,9 +1,5 @@ // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityServer4.Models; - namespace Microsoft.eShopOnContainers.Services.Identity.API.Models { public record ErrorViewModel diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/AddPhoneNumberViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/AddPhoneNumberViewModel.cs index 878b0440b..b01252e03 100644 --- a/src/Services/Identity/Identity.API/Models/ManageViewModels/AddPhoneNumberViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ManageViewModels/AddPhoneNumberViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels { public record AddPhoneNumberViewModel { diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/ChangePasswordViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/ChangePasswordViewModel.cs index 65521429f..e94987e74 100644 --- a/src/Services/Identity/Identity.API/Models/ManageViewModels/ChangePasswordViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ManageViewModels/ChangePasswordViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels { public record ChangePasswordViewModel { diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs index a0a7f30bf..61dbc52e3 100644 --- a/src/Services/Identity/Identity.API/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs @@ -1,7 +1,4 @@ -using Microsoft.AspNetCore.Mvc.Rendering; -using System.Collections.Generic; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels { public record ConfigureTwoFactorViewModel { diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/IndexViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/IndexViewModel.cs index 8d32c8e69..d6b20556b 100644 --- a/src/Services/Identity/Identity.API/Models/ManageViewModels/IndexViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ManageViewModels/IndexViewModel.cs @@ -1,7 +1,4 @@ -using Microsoft.AspNetCore.Identity; -using System.Collections.Generic; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels { public record IndexViewModel { diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/SetPasswordViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/SetPasswordViewModel.cs index e2f048054..51a2758bc 100644 --- a/src/Services/Identity/Identity.API/Models/ManageViewModels/SetPasswordViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ManageViewModels/SetPasswordViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels { public record SetPasswordViewModel { diff --git a/src/Services/Identity/Identity.API/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs b/src/Services/Identity/Identity.API/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs index a3c8e5c65..86859a2e0 100644 --- a/src/Services/Identity/Identity.API/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs +++ b/src/Services/Identity/Identity.API/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels +namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels { public record VerifyPhoneNumberViewModel { diff --git a/src/Services/Identity/Identity.API/Program.cs b/src/Services/Identity/Identity.API/Program.cs index 909680621..7c021c7a4 100644 --- a/src/Services/Identity/Identity.API/Program.cs +++ b/src/Services/Identity/Identity.API/Program.cs @@ -1,18 +1,4 @@ -using IdentityServer4.EntityFramework.DbContexts; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.eShopOnContainers.Services.Identity.API; -using Microsoft.eShopOnContainers.Services.Identity.API.Data; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Serilog; -using System; -using System.IO; - -string Namespace = typeof(Startup).Namespace; +string Namespace = typeof(Startup).Namespace; string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); var configuration = GetConfiguration(); @@ -93,10 +79,11 @@ IConfiguration GetConfiguration() if (config.GetValue("UseVault", false)) { - builder.AddAzureKeyVault( - $"https://{config["Vault:Name"]}.vault.azure.net/", + TokenCredential credential = new ClientSecretCredential( + config["Vault:TenantId"], config["Vault:ClientId"], config["Vault:ClientSecret"]); + builder.AddAzureKeyVault(new Uri($"https://{config["Vault:Name"]}.vault.azure.net/"), credential); } return builder.Build(); diff --git a/src/Services/Identity/Identity.API/Services/EFLoginService.cs b/src/Services/Identity/Identity.API/Services/EFLoginService.cs index 6cee1e7c8..81a5f6a3e 100644 --- a/src/Services/Identity/Identity.API/Services/EFLoginService.cs +++ b/src/Services/Identity/Identity.API/Services/EFLoginService.cs @@ -1,9 +1,4 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Services +namespace Microsoft.eShopOnContainers.Services.Identity.API.Services { public class EFLoginService : ILoginService { diff --git a/src/Services/Identity/Identity.API/Services/ILoginService.cs b/src/Services/Identity/Identity.API/Services/ILoginService.cs index 8b5ba8939..e35b07d6f 100644 --- a/src/Services/Identity/Identity.API/Services/ILoginService.cs +++ b/src/Services/Identity/Identity.API/Services/ILoginService.cs @@ -1,7 +1,4 @@ -using Microsoft.AspNetCore.Authentication; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Services +namespace Microsoft.eShopOnContainers.Services.Identity.API.Services { public interface ILoginService { diff --git a/src/Services/Identity/Identity.API/Services/ProfileService.cs b/src/Services/Identity/Identity.API/Services/ProfileService.cs index b7637fef2..6019b4bd8 100644 --- a/src/Services/Identity/Identity.API/Services/ProfileService.cs +++ b/src/Services/Identity/Identity.API/Services/ProfileService.cs @@ -1,16 +1,4 @@ -using IdentityModel; -using IdentityServer4.Models; -using IdentityServer4.Services; -using Microsoft.AspNetCore.Identity; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; -using System; -using System.Collections.Generic; -using System.IdentityModel.Tokens.Jwt; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Services +namespace Microsoft.eShopOnContainers.Services.Identity.API.Services { public class ProfileService : IProfileService { @@ -25,7 +13,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Services { var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject)); - var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value; + var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault()?.Value; var user = await _userManager.FindByIdAsync(subjectId); if (user == null) @@ -39,7 +27,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Services { var subject = context.Subject ?? throw new ArgumentNullException(nameof(context.Subject)); - var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value; + var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault()?.Value; var user = await _userManager.FindByIdAsync(subjectId); context.IsActive = false; diff --git a/src/Services/Identity/Identity.API/Services/RedirectService.cs b/src/Services/Identity/Identity.API/Services/RedirectService.cs index 64a574d78..4f35e1e92 100644 --- a/src/Services/Identity/Identity.API/Services/RedirectService.cs +++ b/src/Services/Identity/Identity.API/Services/RedirectService.cs @@ -1,6 +1,4 @@ -using System.Text.RegularExpressions; - -namespace Microsoft.eShopOnContainers.Services.Identity.API.Services +namespace Microsoft.eShopOnContainers.Services.Identity.API.Services { public class RedirectService : IRedirectService { diff --git a/src/Services/Identity/Identity.API/Setup/Users.csv b/src/Services/Identity/Identity.API/Setup/Users.csv index 42f582aab..a0955884b 100644 --- a/src/Services/Identity/Identity.API/Setup/Users.csv +++ b/src/Services/Identity/Identity.API/Setup/Users.csv @@ -1,2 +1,2 @@ CardHolderName,CardNumber,CardType,City,Country,Email,Expiration,LastName,Name,PhoneNumber,UserName,ZipCode,State,Street,SecurityNumber,NormalizedEmail,NormalizedUserName,Password -DemoUser,4012888888881881,1,Redmond,U.S.,demouser@microsoft.com,12/21,DemoLastName,DemoUser,1234567890,demouser@microsoft.com,98052,WA,15703 NE 61st Ct,535,DEMOUSER@MICROSOFT.COM,DEMOUSER@MICROSOFT.COM,Pass@word1 \ No newline at end of file +DemoUser,4012888888881881,1,Redmond,U.S.,demouser@microsoft.com,12/25,DemoLastName,DemoUser,1234567890,demouser@microsoft.com,98052,WA,15703 NE 61st Ct,535,DEMOUSER@MICROSOFT.COM,DEMOUSER@MICROSOFT.COM,Pass@word1 \ No newline at end of file diff --git a/src/Services/Identity/Identity.API/Startup.cs b/src/Services/Identity/Identity.API/Startup.cs index 4e888fbb5..daba44e72 100644 --- a/src/Services/Identity/Identity.API/Startup.cs +++ b/src/Services/Identity/Identity.API/Startup.cs @@ -1,26 +1,4 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using HealthChecks.UI.Client; -using IdentityServer4.Services; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Identity; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Identity.API.Certificates; -using Microsoft.eShopOnContainers.Services.Identity.API.Data; -using Microsoft.eShopOnContainers.Services.Identity.API.Devspaces; -using Microsoft.eShopOnContainers.Services.Identity.API.Models; -using Microsoft.eShopOnContainers.Services.Identity.API.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using StackExchange.Redis; -using System; -using System.Reflection; +using Microsoft.AspNetCore.DataProtection; namespace Microsoft.eShopOnContainers.Services.Identity.API { @@ -112,7 +90,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API services.AddRazorPages(); var container = new ContainerBuilder(); - container.Populate(services); + container.Populate(services); return new AutofacServiceProvider(container.Build()); } @@ -132,18 +110,18 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API else { app.UseExceptionHandler("/Home/Error"); - } + } var pathBase = Configuration["PATH_BASE"]; if (!string.IsNullOrEmpty(pathBase)) { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + //loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); app.UsePathBase(pathBase); } app.UseStaticFiles(); - // Make work identity server redirections in Edge and lastest versions of browers. WARN: Not valid in a production environment. + // Make work identity server redirections in Edge and lastest versions of browsers. WARN: Not valid in a production environment. app.Use(async (context, next) => { context.Response.Headers.Add("Content-Security-Policy", "script-src 'unsafe-inline'"); @@ -158,10 +136,11 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API app.UseIdentityServer(); // Fix a problem with chrome. Chrome enabled a new feature "Cookies without SameSite must be secure", - // the coockies shold be expided from https, but in eShop, the internal comunicacion in aks and docker compose is http. - // To avoid this problem, the policy of cookies shold be in Lax mode. + // the cookies should be expired from https, but in eShop, the internal communication in aks and docker compose is http. + // To avoid this problem, the policy of cookies should be in Lax mode. app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = AspNetCore.Http.SameSiteMode.Lax }); app.UseRouting(); + app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); diff --git a/src/Services/Identity/Identity.API/Views/Account/Login.cshtml b/src/Services/Identity/Identity.API/Views/Account/Login.cshtml index b74d7d8b9..049381b0d 100644 --- a/src/Services/Identity/Identity.API/Views/Account/Login.cshtml +++ b/src/Services/Identity/Identity.API/Views/Account/Login.cshtml @@ -1,61 +1,27 @@ @model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.LoginViewModel - @{ ViewData["Title"] = "Log in"; + + var requestQuery = ViewContext.HttpContext.Request.Query; + + requestQuery.TryGetValue("ReturnUrl", out var returnUrl); + + string partialView; + + if (returnUrl[0].Contains("client_id=js")) + { + Layout = "_Layout-SPA"; + partialView = "_LoginPartial-SPA.cshtml"; + } + else + { + partialView = "_LoginPartial-MVC.cshtml"; + } + } -
- -
- + + @section Scripts { @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } diff --git a/src/Services/Identity/Identity.API/Views/Account/Register.cshtml b/src/Services/Identity/Identity.API/Views/Account/Register.cshtml index 838dad5c7..f9bffbca0 100644 --- a/src/Services/Identity/Identity.API/Views/Account/Register.cshtml +++ b/src/Services/Identity/Identity.API/Views/Account/Register.cshtml @@ -1,106 +1,28 @@ @model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.RegisterViewModel + @{ ViewData["Title"] = "Register"; + + var requestQuery = ViewContext.HttpContext.Request.Query; + + requestQuery.TryGetValue("ReturnUrl", out var returnUrl); + + string partialView; + + if (returnUrl[0].Contains("client_id=js")) + { + Layout = "_Layout-SPA"; + partialView = "_RegisterPartial-SPA.cshtml"; + } + else + { + partialView = "_RegisterPartial-MVC.cshtml"; + } + } -
- -
-
-
-

CREATE NEW ACCOUNT

-
-
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
-

-
-
- - - -
-
-
- - - -
-
- - - -
-
-

-
- -
-

-
-
+ + + @section Scripts { @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } } - diff --git a/src/Services/Identity/Identity.API/Views/Account/_LoginPartial-MVC.cshtml b/src/Services/Identity/Identity.API/Views/Account/_LoginPartial-MVC.cshtml new file mode 100644 index 000000000..9094ba6f4 --- /dev/null +++ b/src/Services/Identity/Identity.API/Views/Account/_LoginPartial-MVC.cshtml @@ -0,0 +1,54 @@ +@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.LoginViewModel + +
+ +
+ diff --git a/src/Services/Identity/Identity.API/Views/Account/_LoginPartial-SPA.cshtml b/src/Services/Identity/Identity.API/Views/Account/_LoginPartial-SPA.cshtml new file mode 100644 index 000000000..0609a362d --- /dev/null +++ b/src/Services/Identity/Identity.API/Views/Account/_LoginPartial-SPA.cshtml @@ -0,0 +1,47 @@ +@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.LoginViewModel + +
+
+
+
+ + +
+
+
+
diff --git a/src/Services/Identity/Identity.API/Views/Account/_RegisterPartial-MVC.cshtml b/src/Services/Identity/Identity.API/Views/Account/_RegisterPartial-MVC.cshtml new file mode 100644 index 000000000..7fa6b0111 --- /dev/null +++ b/src/Services/Identity/Identity.API/Views/Account/_RegisterPartial-MVC.cshtml @@ -0,0 +1,100 @@ +@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.RegisterViewModel + +
+ +
+
+
+

CREATE NEW ACCOUNT

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+

+
+
+ + + +
+
+
+ + + +
+
+ + + +
+
+

+
+ +
+

+
+
diff --git a/src/Services/Identity/Identity.API/Views/Account/_RegisterPartial-SPA.cshtml b/src/Services/Identity/Identity.API/Views/Account/_RegisterPartial-SPA.cshtml new file mode 100644 index 000000000..899499c10 --- /dev/null +++ b/src/Services/Identity/Identity.API/Views/Account/_RegisterPartial-SPA.cshtml @@ -0,0 +1,100 @@ +@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.RegisterViewModel + +
+

[ New Account ]

+
+

Information

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+

Credit Card

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+

+
+
+ + + +
+
+
+ + + +
+
+ + + +
+
+

+
+ +
+

+
+
diff --git a/src/Services/Identity/Identity.API/Views/Shared/_Layout-SPA.cshtml b/src/Services/Identity/Identity.API/Views/Shared/_Layout-SPA.cshtml new file mode 100644 index 000000000..fab01ff51 --- /dev/null +++ b/src/Services/Identity/Identity.API/Views/Shared/_Layout-SPA.cshtml @@ -0,0 +1,54 @@ + + + + + + + eShopOnContainers - Identity + + + + + + + + + + + + +
+
+ +
+
+ +
+ @RenderBody() +
+ +
+
+
+
+ +
+
© e-Shoponcontainers. All rights reserved
+
+
+
+ + + + + @RenderSection("scripts", required: false) + + diff --git a/src/Services/Identity/Identity.API/wwwroot/css/site-spa.css b/src/Services/Identity/Identity.API/wwwroot/css/site-spa.css new file mode 100644 index 000000000..2a98a4ed7 --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/css/site-spa.css @@ -0,0 +1,1062 @@ +.navbar-header { + position: relative; + top: -4px; +} + +.navbar-brand>.icon-banner { + position: relative; + top: -2px; + display: inline; +} + +.icon { + position: relative; + top: -10px; +} + +.welcome-title { + margin-top:2rem; +} + +.page-consent .client-logo { + float: left; +} + +.page-consent .client-logo img { + width: 80px; + height: 80px; +} + +.page-consent .consent-buttons { + margin-top: 25px; +} + +.page-consent .consent-form .consent-scopecheck { + display: inline-block; + margin-right: 5px; +} + +.page-consent .consent-form .consent-description { + margin-left: 25px; +} + +.page-consent .consent-form .consent-description label { + font-weight: normal; +} + +.page-consent .consent-form .consent-remember { + padding-left: 16px; +} + +@font-face { + font-family: 'Oswald'; + src: url('../fonts/Oswald-Medium.eot'); + src: url('../fonts/Oswald-Medium.eot?#iefix') format('embedded-opentype'), + url('../fonts/Oswald-Medium.woff2') format('woff2'), + url('../fonts/Oswald-Medium.woff') format('woff'), + url('../fonts/Oswald-Medium.ttf') format('truetype'), + url('../fonts/Oswald-Medium.svg#Oswald-Medium') format('svg'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'Oswald'; + src: url('../fonts/Oswald-ExtraLight.eot'); + src: url('../fonts/Oswald-ExtraLight.eot?#iefix') format('embedded-opentype'), + url('../fonts/Oswald-ExtraLight.woff2') format('woff2'), + url('../fonts/Oswald-ExtraLight.woff') format('woff'), + url('../fonts/Oswald-ExtraLight.ttf') format('truetype'), + url('../fonts/Oswald-ExtraLight.svg#Oswald-ExtraLight') format('svg'); + font-weight: 200; + font-style: normal; +} + +@font-face { + font-family: 'Oswald'; + src: url('../fonts/Oswald-Regular.eot'); + src: url('../fonts/Oswald-Regular.eot?#iefix') format('embedded-opentype'), + url('../fonts/Oswald-Regular.woff2') format('woff2'), + url('../fonts/Oswald-Regular.woff') format('woff'), + url('../fonts/Oswald-Regular.ttf') format('truetype'), + url('../fonts/Oswald-Regular.svg#Oswald-Regular') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'Oswald'; + src: url('../fonts/Oswald-Bold.eot'); + src: url('../fonts/Oswald-Bold.eot?#iefix') format('embedded-opentype'), + url('../fonts/Oswald-Bold.woff2') format('woff2'), + url('../fonts/Oswald-Bold.woff') format('woff'), + url('../fonts/Oswald-Bold.ttf') format('truetype'), + url('../fonts/Oswald-Bold.svg#Oswald-Bold') format('svg'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'Oswald'; + src: url('../fonts/Oswald-Light.eot'); + src: url('../fonts/Oswald-Light.eot?#iefix') format('embedded-opentype'), + url('../fonts/Oswald-Light.woff2') format('woff2'), + url('../fonts/Oswald-Light.woff') format('woff'), + url('../fonts/Oswald-Light.ttf') format('truetype'), + url('../fonts/Oswald-Light.svg#Oswald-Light') format('svg'); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: 'Oswald'; + src: url('../fonts/Oswald-SemiBold.eot'); + src: url('../fonts/Oswald-SemiBold.eot?#iefix') format('embedded-opentype'), + url('../fonts/Oswald-SemiBold.woff2') format('woff2'), + url('../fonts/Oswald-SemiBold.woff') format('woff'), + url('../fonts/Oswald-SemiBold.ttf') format('truetype'), + url('../fonts/Oswald-SemiBold.svg#Oswald-SemiBold') format('svg'); + font-weight: 600; + font-style: normal; +} + +html, body { + background-color: #f3f4f3; + font-family: Oswald, sans-serif; + font-size: 16px; + font-weight: normal; + min-width: 480px; +} + +html { + height: 100%; +} + +body { + display: flex; + flex-direction: column; + min-height: 100%; +} + +::selection { + background: rgba(#f66f61, .75); +} + +.mt-15 { + margin-top: 15px; +} + +/* Wrapping element */ + +/* Set some basic padding to keep content from hitting the edges */ + +.body-content { + padding-left: 15px; + padding-right: 15px; +} + +/* Set widths on the form inputs since otherwise they're 100% wide */ + +.select-filter { + background-color: transparent; + padding: 10px; + margin: 10px; + margin-right: 20px; + color: white; + padding-top: 20px; + padding-bottom: 3px; + min-width: 140px; + border-color: #37c7ca; + max-height: 43px; + -webkit-appearance: none; +} + +.select-filter option { + background-color: #00a69c; +} + +select::-ms-expand { + display: none; +} + +.select-filter-wrapper { + z-index: 0; + display: inline-block; + margin-left: -10px; +} + +.select-filter-wrapper::before { + content: attr(data-name); + opacity: 0.5; + z-index: 1; + text-transform: uppercase; + position: absolute; + font-size: 10px; + margin-top: 15px; + margin-left: 21px; + color: white; +} + +.select-filter-arrow { + position: absolute; + margin-left: 130px; + margin-top: 40px; +} + +.btn-brand-small-filter { + margin-top: 10px; + position: absolute; + margin-left: 15px; +} + +/* Carousel */ + +.carousel-caption p { + font-size: 20px; + line-height: 1.4; +} + +.layout-cart-image { + height: 36px; + margin-top: 5px; +} + +.layout-cart-badge { + position: absolute; + margin-top: 2px; + margin-left: 14px; + background-color: #83d01b; + padding: 1px; + color: white; + border-radius: 50%; + width: 18px; + height: 18px; + font-size: 12px; + cursor: pointer; +} + +/* buttons and links extension to use brackets: [ click me ] */ + +.btn-bracketed:hover:before { + display: inline-block; + content: "["; + padding-right: 0.5em; + color: chartreuse; +} + +.btn-bracketed:hover:after { + display: inline-block; + content: "]"; + padding-left: 0.5em; + color: chartreuse; +} + +.btn { + background-color: transparent; + border-radius: 0; + border-width: 3px; + font-size: .875rem; + font-weight: 400; + min-width: 15rem; + text-transform: uppercase; +} + +.btn:focus { + box-shadow: unset; +} + +.btn-primary { + border-color:#f66f61; + color:#f66f61; +} + +.btn-primary:hover { + color: #fff; + background-color: #f44e3d; + border-color: #f34331; +} + +.btn-primary:focus { + box-shadow: none; + opacity: .7; + color: #fff !important; + background-color: #f44e3d !important; + border-color: #f34331 !important; +} + +.btn-primary:active { + box-shadow: none; + opacity: .7; + color: #fff !important; + background-color: #f44e3d !important; + border-color: #f34331 !important; +} + +.btn-secondary { + border-color:#292929; + color:#292929; +} + +.btn-secondary: hover { + color: #fff; + background-color: #292929; + border-color: #292929; +} + +.btn-secondary:focus { + box-shadow: none; + opacity: .7; + color: #fff !important; + background-color: #292929 !important; + border-color: #292929 !important; +} + +.btn-secondary:active { + box-shadow: none; + opacity: .7; + color: #fff !important; + background-color: #292929 !important; + border-color: #292929 !important; +} + +.btn-cart { + float: right; + margin-top: 40px; + margin-bottom: 40px; +} + +.btn-catalog-apply { + padding: 0; +} + +.form-label { + font-weight: normal!important; + text-align: left; + margin-bottom: .2rem; + color: #292929; +} + +.form-input { + border-radius: 0; + padding: 10px; + height: 45px; +} + +.form-input-small { + max-width: 100px!important; +} + +.form-select { + border-radius: 0; + padding: 10px; + height: 45px; + width: 150px; +} + +/* Make .svg files in the carousel display properly in older browsers */ + +.carousel-inner .item img[src$=".svg"] { + width: 100%; +} + +.navbar-inverse { + background-color: #FFF; + border-color: #FFF; +} + +/*.navbar-inverse li { + margin-top: 10px; + }*/ + +.btn-login { + border: 1px solid #00A69C; + height: 36px!important; + margin-right: 10px; + margin-top: 10px; + background-color: white; + color: #00a69c; + text-transform: uppercase; + max-width: 140px; + width: 140px; + padding-top: 8px!important; +} + +.btn-login { + font-weight: normal!important; +} + +.btn-login::before { + content: '['; +} + +.btn-login::after { + content: ']'; +} + +.btn-login:hover:before { + content: '[ '; +} + +.btn-login:hover:after { + content: ' ]'; +} + + +.nav>li>a { + color: white; +} + +.nav>li>a:hover, .nav>li>a:focus { + background-color: #00A69C; + font-weight: bolder; +} + +.container-fluid { + padding-left: 0px; + padding-right: 0px; +} + +.home-banner { + width: 100%; + margin-right: 0px; + margin-left: 0px; + background-image: url(../images/main_banner.png); + background-size: cover; + height: 258px; + background-position: center; +} + +.home-banner-text { + margin-top: 70px; +} + +.home-catalog-container { + min-height: 400px; + margin-bottom: 20px; +} + +.home-catalog-filter-container { + background-color: #00A69C; + height: 63px; + line-height: 76px; +} + +.home-catalog-filter-container li a { + padding-top: 5px !important; +} + +.home-catalog-filter-brands::before { + content: 'BRAND'; + color: white; + font-size: x-small; + opacity: 0.5; + margin: 10px 0px 0px 15px; +} + +.home-catalog-filter-types::before { + content: 'TYPES'; + color: white; + font-size: x-small; + opacity: 0.5; + margin: 10px 0px 0px 15px; +} + +.home-catalog-item { + margin-top: 10px; + margin-bottom: 10px; +} + +.home-catalog-item-image { + width: 100%; + object-fit: cover; + /* max-width: 320px; */ + text-align: center; +} + +.home-catalog-item-image-addCart { + background-color: #83D01B; + color: white; + display: inline-block; + height: 43px; + padding: 10px 20px 10px 20px; + font-weight: bold; + text-align: center; + margin-top: 10px; + margin-left: 60px; + margin-right: 60px; + font-size: 16px; + font-weight: normal; +} + +.home-catalog-item-image-addCart:hover { + color: white; + text-decoration: none; +} + +.home-catalog-item-image:hover:after { + cursor: pointer; +} + +.home-catalog-item-title { + text-align: center; + text-transform: uppercase; + font-weight: 300; + font-size: 16px; + margin-top: 20px; +} + +.home-catalog-item-price { + text-align: center; + font-weight: 900; + font-size: 28px; +} + +.home-catalog-item-price::before { + content: '$'; +} + +.home-catalog-noResults { + text-align: center; + margin-top: 100px; +} + +.container .nav .navbar-nav .col-sm-6 ::before { + content: 'BRAND'; +} + +.validation-summary-errors li { + list-style: none; +} + +footer { + background-color: black; + height: 150px; + vertical-align: middle; +} + +footer .brand { + margin-top: 25px; + background-image: url(../images/brand_dark.PNG); + max-width: 231px; + height: 52px; + margin-left: 0px !important; +} + +footer .text { + margin-top: 55px; +} + +.text { + color: #83D01B; +} + +.text:hover { + color: #83D01B; +} + +form .col-md-4 { + text-align: right; +} + +.brand-header-block { + background-color: #00A69C; + height: 63px; +} + +.brand-header-block li { + list-style: none; + display: inline; + opacity: 0.5; + margin-top: 25px; + margin-left: 10px; + /*float: right;*/ + cursor: pointer; + color: white; +} + +.brand-header-block li a { + color: white; +} + +.brand-header-block li a:hover { + text-decoration: none; +} + +.brand-header-block .active { + opacity: 1; +} + +.brand-header-block .active::before { + content: '[ '; + color: greenyellow; +} + +.brand-header-block .active::after { + content: ' ]'; + color: greenyellow; +} + +.brand-header-back { + float: left!important; + margin-top: 20px!important; + text-transform: uppercase; +} + +.account-register-container { + min-height: 70vh; + text-align: center !important; + align-content: center; +} + +.cart-index-container { + min-height: 70vh; + padding-top: 40px; + margin-bottom: 30px; + min-width: 992px; +} + +.register-container { + min-height: 70vh; + padding-top: 40px; + margin-bottom: 30px; + padding-left: 30px; +} + +.order-create-container { + min-height: 70vh; + padding-top: 40px; + margin-bottom: 30px; + padding-left: 30px; + min-width: 995px; +} + +.cart-product-column { + max-width: 120px; + text-transform: uppercase; + vertical-align: middle!important; +} + +.order-create-container .cart-product-column { + max-width: 130px; +} + +.cart-product-column-name { + width: 220px; +} + +.cart-subtotal-label { + font-size: 12px; + color: #404040; + margin-top: 10px; +} + +.cart-subtotal-value { + font-size: 20px; + color: #00a69c; +} + +.cart-total-label { + font-size: 14px; + color: #404040; + margin-top: 10px; +} + +.cart-total-value { + font-size: 28px; + color: #00a69c; + text-align: left; +} + +.cart-product-image { + max-width: 210px; +} + +.cart-section-total { + margin-bottom: 5px; + margin-left: 175px; + text-align: left; +} + +.cart-product-column input { + width: 70px; + text-align: center; +} + +.cart-refresh-button { + margin-top: 0; + background-image: url('../images/refresh.svg'); + color: white; + font-size: 8px; + width: 40px; + height: 40px; + background-color: transparent; + border: none; + margin-top: 25px; + margin-left: 15px; +} + +.cart-refresh-button:hover { + background-color: transparent; +} + +.cart-totals { + border-bottom: none!important; +} + +.input-validation-error { + border: 1px solid #fb0d0d; +} + +.text-danger { + color: #fb0d0d; + font-size: 12px; +} + +.cart { + border: none !important; +} + +.text-link { + color: #f66f61; +} + +.text-link:hover { + color: #292929; + text-decoration: none; +} + +.form-group { + margin-bottom: 2rem; +} + +.form-control { + border-width: 2px; + border-radius: 0; + border-color: #292929; + font-size: 1rem; + font-weight: 300; +} + +.form-control:hover { + border-color: #81828D; +} + +.form-control:focus { + border-color: #f66f61; + box-shadow: unset; +} + +.form-control:visited { + text-decoration: unset; +} + +.form-register { + background-color: #fff; + color: #292929; + padding-bottom: 2rem; + padding-left: 6rem; + padding-right: 6rem; + padding-top: 4rem; +} + +.form-login { + background-color: #fff; + color: #292929; + margin: 4rem auto 0 auto; + padding-bottom: 2rem; + padding-left: 6rem; + padding-right: 6rem; + padding-top: 4rem; + width: 47rem; +} + +.form-login-details { + background-color: #fff; + border-top: 3px solid #F3F4F3; + color: #81828D; + font-size: 16px; + margin: 0 auto 0 auto; + padding-bottom: 2rem; + padding-top: 2rem; + padding-left: 6rem; + padding-right: 6rem; + width: 47rem; +} + +.form-login-register-link { + margin-left: auto; + width: 15rem; +} + + +.order-index-container { + min-height: 70vh; + padding-top: 40px; + margin-bottom: 30px; +} + +.order-index-container .table tbody tr { + border-bottom: none; +} + +.order-index-container .table tbody tr td { + border-top: none; + padding-top: 10px; + padding-bottom: 10px; +} + +.order-index-container .table tbody tr:nth-child(even) { + background-color: #f5f5f5; +} + +.order-create-section-title { + margin-left: -15px; + text-transform: uppercase; +} + +.order-create-section-items { + margin-left: -45px; + width: 102%; +} + +.order-detail-button {} + +.order-detail-button a { + color: #83d01b; +} + +.order-detail-container { + min-height: 70vh; + padding-top: 40px; + margin-bottom: 30px; +} + +.order-detail-container .table tbody tr:first-child td { + border-top: none; +} + +.order-detail-container .table tr { + border-bottom: none; +} + +.order-detail-section { + margin-top: 50px; +} + +.order-detail-container .table { + margin-left: -7px; +} + +.order-section-total { + margin-bottom: 5px; + margin-left: 40px; + text-align: left; +} + +.fr { + float: right!important; +} + +.down-arrow { + background-image: url('../images/arrow-down.png'); + height: 7px; + width: 10px; + display: inline-block; + margin-left: 20px; +} + +.logout-icon { + background-image: url('../images/logout.PNG'); + display: inline-block; + height: 19px; + width: 19px; + margin-left: 15px; +} + +.myorders-icon { + background-image: url('../images/my_orders.PNG'); + display: inline-block; + height: 20px; + width: 20px; + margin-left: 15px; +} + +.login-user { + position: absolute!important; + top: 30px; + right: 65px; + cursor: pointer; +} + +.login-user-dropdown { + position: relative; + display: inline-block; +} + +.login-user-dropdown-content { + display: none; + position: absolute; + background-color: #FFFFFF; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + /*left: 100px;*/ + right: 0px; +} + +.login-user-dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; + text-align: right; + text-transform: uppercase; +} + +.login-user:hover .login-user-dropdown-content { + display: block; +} + +.down-arrow:hover>.login-user-dropdown-content { + display: block; +} + +.login-user-dropdown-content a:hover { + color: #83d01b; +} + +.es-header { + background: url(../images/header.jpg) center -2.7rem no-repeat,linear-gradient(90deg,#5F6571 0%, #5F6571 35%, #CFC6BF 65%, #CFC6BF 100%); + background-size: auto, auto; + background-size: 94rem,auto; + height: 13rem; + padding-top: 2.25rem; + position: relative; + transition: all .35s; +} + +.es-header-brand { + height: auto; + width: 92px; +} + +.es-pager-bottom { + margin-top: 40px; +} + +.es-pager-top { + margin-bottom: 20px; + margin-top: 20px; +} + +.es-pager-top ul { + list-style: none; +} + +.es-pager-bottom ul { + list-style: none; +} + +.page-item { + cursor: pointer; +} + +.next { + position: absolute; + right: 15px; + top: 0; +} + +.previous { + position: absolute; + left: 0; + top: 0; +} + +.is-disabled { + cursor: not-allowed; + opacity: .5; + pointer-events: none; +} + +.table tr { + border-bottom: 1px solid #ddd; +} + +.table th { + text-transform: uppercase; +} + +.navbar-nav { + margin-top: 10px; + margin-bottom: 7.5px; + margin-right: -10px; + float: right; +} + +.content { + margin-bottom: 3rem; +} + +.footer { + background-color:#81828d; + color:#fff; + font-size: 1rem; + display: flex; + height: 7rem; + margin-top: auto; +} + +.footer-brand { + height: auto; + width: 104px; +} + +h1 { + font-size: 1.5625rem; + font-weight: 400; + text-transform: uppercase; +} + +h2 { + font-size: 1.4375rem; + font-weight: 400; + text-transform: uppercase; +} + +@media screen and (max-width: 1195px) { + .cart-product-column-name { + display: none; + } +} + +/* Hide/rearrange for smaller screens */ + +@media screen and (max-width: 767px) { + /* Hide captions */ + .carousel-caption { + display: none; + } + footer .text { + text-align: left; + margin-top: -15px; + } + .cart-product-column-brand { + display: none; + } +} + +@media screen and (max-width: 415px) { + .account-login-container { + margin-left: -50px; + } + .page-consent { + margin-left: 10px; + margin-right: 80px; + padding-right: 0px; + padding-left: 0px; + } +} + +::selection { + background: rgba(246, 111, 97, .75); +} diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.eot b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.eot new file mode 100644 index 000000000..1d59b4860 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.eot differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.svg b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.svg new file mode 100644 index 000000000..ca947a830 --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.svg @@ -0,0 +1,3184 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.ttf b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.ttf new file mode 100644 index 000000000..b36d676e1 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.ttf differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.woff b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.woff new file mode 100644 index 000000000..3235009f1 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.woff differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.woff2 b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.woff2 new file mode 100644 index 000000000..b9363b1d2 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Bold.woff2 differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.eot b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.eot new file mode 100644 index 000000000..ea55b5d88 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.eot differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.svg b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.svg new file mode 100644 index 000000000..822eec9d3 --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.svg @@ -0,0 +1,2860 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.ttf b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.ttf new file mode 100644 index 000000000..c5f704498 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.ttf differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.woff b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.woff new file mode 100644 index 000000000..843da1430 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.woff differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.woff2 b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.woff2 new file mode 100644 index 000000000..42cfba52c Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-ExtraLight.woff2 differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.eot b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.eot new file mode 100644 index 000000000..d95eec454 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.eot differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.svg b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.svg new file mode 100644 index 000000000..50f1d7539 --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.svg @@ -0,0 +1,2902 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.ttf b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.ttf new file mode 100644 index 000000000..d70424cd8 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.ttf differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.woff b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.woff new file mode 100644 index 000000000..3c448fca4 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.woff differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.woff2 b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.woff2 new file mode 100644 index 000000000..6e9b9a97a Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Light.woff2 differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.eot b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.eot new file mode 100644 index 000000000..e8a3c5094 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.eot differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.svg b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.svg new file mode 100644 index 000000000..fa9da77bf --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.svg @@ -0,0 +1,3232 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.ttf b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.ttf new file mode 100644 index 000000000..d0ab912cf Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.ttf differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.woff b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.woff new file mode 100644 index 000000000..6af5288a6 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.woff differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.woff2 b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.woff2 new file mode 100644 index 000000000..b7514b872 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Medium.woff2 differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.eot b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.eot new file mode 100644 index 000000000..10c4df61d Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.eot differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.svg b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.svg new file mode 100644 index 000000000..a28247311 --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.svg @@ -0,0 +1,2720 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.ttf b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.ttf new file mode 100644 index 000000000..2492c44a2 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.ttf differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.woff b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.woff new file mode 100644 index 000000000..1aff4945d Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.woff differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.woff2 b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.woff2 new file mode 100644 index 000000000..626d517ec Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-Regular.woff2 differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.eot b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.eot new file mode 100644 index 000000000..bd08ba217 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.eot differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.svg b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.svg new file mode 100644 index 000000000..2114fe93e --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.svg @@ -0,0 +1,3197 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.ttf b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.ttf new file mode 100644 index 000000000..b1b50d68f Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.ttf differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.woff b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.woff new file mode 100644 index 000000000..305eb488a Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.woff differ diff --git a/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.woff2 b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.woff2 new file mode 100644 index 000000000..e31be5404 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/fonts/Oswald-SemiBold.woff2 differ diff --git a/src/Services/Identity/Identity.API/wwwroot/images/header.jpg b/src/Services/Identity/Identity.API/wwwroot/images/header.jpg new file mode 100644 index 000000000..c8aa750c8 Binary files /dev/null and b/src/Services/Identity/Identity.API/wwwroot/images/header.jpg differ diff --git a/src/Services/Identity/Identity.API/wwwroot/images/logo.svg b/src/Services/Identity/Identity.API/wwwroot/images/logo.svg new file mode 100644 index 000000000..1e736705c --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/images/logo.svg @@ -0,0 +1,14 @@ + + + + Group 5 + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/src/Services/Identity/Identity.API/wwwroot/images/logo_color.svg b/src/Services/Identity/Identity.API/wwwroot/images/logo_color.svg new file mode 100644 index 000000000..e56235262 --- /dev/null +++ b/src/Services/Identity/Identity.API/wwwroot/images/logo_color.svg @@ -0,0 +1,14 @@ + + + + Group 5 + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs index 8bcb07b89..1ec015488 100644 --- a/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs +++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/LoggingBehavior.cs @@ -1,23 +1,16 @@ -using MediatR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; - -namespace Ordering.API.Application.Behaviors +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Behaviors; +public class LoggingBehavior : IPipelineBehavior where TRequest : IRequest { - public class LoggingBehavior : IPipelineBehavior - { - private readonly ILogger> _logger; - public LoggingBehavior(ILogger> logger) => _logger = logger; + private readonly ILogger> _logger; + public LoggingBehavior(ILogger> logger) => _logger = logger; - public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) - { - _logger.LogInformation("----- Handling command {CommandName} ({@Command})", request.GetGenericTypeName(), request); - var response = await next(); - _logger.LogInformation("----- Command {CommandName} handled - response: {@Response}", request.GetGenericTypeName(), response); + public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) + { + _logger.LogInformation("----- Handling command {CommandName} ({@Command})", request.GetGenericTypeName(), request); + var response = await next(); + _logger.LogInformation("----- Command {CommandName} handled - response: {@Response}", request.GetGenericTypeName(), response); - return response; - } + return response; } } + diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs index be32daeee..24949869e 100644 --- a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs +++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs @@ -1,74 +1,64 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Behaviors; + using Microsoft.Extensions.Logging; -using Ordering.API.Application.IntegrationEvents; -using Serilog.Context; -using System; -using System.Threading; -using System.Threading.Tasks; -namespace Ordering.API.Application.Behaviors +public class TransactionBehaviour : IPipelineBehavior where TRequest : IRequest { - public class TransactionBehaviour : IPipelineBehavior + private readonly ILogger> _logger; + private readonly OrderingContext _dbContext; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + + public TransactionBehaviour(OrderingContext dbContext, + IOrderingIntegrationEventService orderingIntegrationEventService, + ILogger> logger) { - private readonly ILogger> _logger; - private readonly OrderingContext _dbContext; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + _dbContext = dbContext ?? throw new ArgumentException(nameof(OrderingContext)); + _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentException(nameof(orderingIntegrationEventService)); + _logger = logger ?? throw new ArgumentException(nameof(ILogger)); + } - public TransactionBehaviour(OrderingContext dbContext, - IOrderingIntegrationEventService orderingIntegrationEventService, - ILogger> logger) - { - _dbContext = dbContext ?? throw new ArgumentException(nameof(OrderingContext)); - _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentException(nameof(orderingIntegrationEventService)); - _logger = logger ?? throw new ArgumentException(nameof(ILogger)); - } + public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) + { + var response = default(TResponse); + var typeName = request.GetGenericTypeName(); - public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) + try { - var response = default(TResponse); - var typeName = request.GetGenericTypeName(); - - try + if (_dbContext.HasActiveTransaction) { - if (_dbContext.HasActiveTransaction) - { - return await next(); - } + return await next(); + } - var strategy = _dbContext.Database.CreateExecutionStrategy(); + var strategy = _dbContext.Database.CreateExecutionStrategy(); - await strategy.ExecuteAsync(async () => - { - Guid transactionId; + await strategy.ExecuteAsync(async () => + { + Guid transactionId; - using (var transaction = await _dbContext.BeginTransactionAsync()) - using (LogContext.PushProperty("TransactionContext", transaction.TransactionId)) - { - _logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request); + using var transaction = await _dbContext.BeginTransactionAsync(); + using (LogContext.PushProperty("TransactionContext", transaction.TransactionId)) + { + _logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request); - response = await next(); + response = await next(); - _logger.LogInformation("----- Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName); + _logger.LogInformation("----- Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName); - await _dbContext.CommitTransactionAsync(transaction); + await _dbContext.CommitTransactionAsync(transaction); - transactionId = transaction.TransactionId; - } + transactionId = transaction.TransactionId; + } - await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync(transactionId); - }); + await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync(transactionId); + }); - return response; - } - catch (Exception ex) - { - _logger.LogError(ex, "ERROR Handling transaction for {CommandName} ({@Command})", typeName, request); + return response; + } + catch (Exception ex) + { + _logger.LogError(ex, "ERROR Handling transaction for {CommandName} ({@Command})", typeName, request); - throw; - } + throw; } } } diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs index 00d88da5f..158254bce 100644 --- a/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs +++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/ValidatorBehavior.cs @@ -1,46 +1,36 @@ -using FluentValidation; -using MediatR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.Extensions.Logging; -using Ordering.Domain.Exceptions; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace Ordering.API.Application.Behaviors -{ - public class ValidatorBehavior : IPipelineBehavior - { - private readonly ILogger> _logger; - private readonly IValidator[] _validators; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Behaviors; - public ValidatorBehavior(IValidator[] validators, ILogger> logger) - { - _validators = validators; - _logger = logger; - } +public class ValidatorBehavior : IPipelineBehavior where TRequest : IRequest +{ + private readonly ILogger> _logger; + private readonly IEnumerable> _validators; - public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) - { - var typeName = request.GetGenericTypeName(); + public ValidatorBehavior(IEnumerable> validators, ILogger> logger) + { + _validators = validators; + _logger = logger; + } - _logger.LogInformation("----- Validating command {CommandType}", typeName); + public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) + { + var typeName = request.GetGenericTypeName(); - var failures = _validators - .Select(v => v.Validate(request)) - .SelectMany(result => result.Errors) - .Where(error => error != null) - .ToList(); + _logger.LogInformation("----- Validating command {CommandType}", typeName); - if (failures.Any()) - { - _logger.LogWarning("Validation errors - {CommandType} - Command: {@Command} - Errors: {@ValidationErrors}", typeName, request, failures); + var failures = _validators + .Select(v => v.Validate(request)) + .SelectMany(result => result.Errors) + .Where(error => error != null) + .ToList(); - throw new OrderingDomainException( - $"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures)); - } + if (failures.Any()) + { + _logger.LogWarning("Validation errors - {CommandType} - Command: {@Command} - Errors: {@ValidationErrors}", typeName, request, failures); - return await next(); + throw new OrderingDomainException( + $"Command Validation Errors for type {typeof(TRequest).Name}", new ValidationException("Validation exception", failures)); } + + return await next(); } } \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs index 408abf2b8..0c7dcb940 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs @@ -1,20 +1,16 @@ -using MediatR; -using System.Runtime.Serialization; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +public class CancelOrderCommand : IRequest { - public class CancelOrderCommand : IRequest - { - [DataMember] - public int OrderNumber { get; set; } - public CancelOrderCommand() - { + [DataMember] + public int OrderNumber { get; set; } + public CancelOrderCommand() + { - } - public CancelOrderCommand(int orderNumber) - { - OrderNumber = orderNumber; - } + } + public CancelOrderCommand(int orderNumber) + { + OrderNumber = orderNumber; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs index 11313d9f1..74535c3f8 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommandHandler.cs @@ -1,57 +1,48 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +// Regular CommandHandler +public class CancelOrderCommandHandler : IRequestHandler { - // Regular CommandHandler - public class CancelOrderCommandHandler : IRequestHandler + private readonly IOrderRepository _orderRepository; + + public CancelOrderCommandHandler(IOrderRepository orderRepository) { - private readonly IOrderRepository _orderRepository; + _orderRepository = orderRepository; + } - public CancelOrderCommandHandler(IOrderRepository orderRepository) + /// + /// Handler which processes the command when + /// customer executes cancel order from app + /// + /// + /// + public async Task Handle(CancelOrderCommand command, CancellationToken cancellationToken) + { + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if (orderToUpdate == null) { - _orderRepository = orderRepository; + return false; } - /// - /// Handler which processes the command when - /// customer executes cancel order from app - /// - /// - /// - public async Task Handle(CancelOrderCommand command, CancellationToken cancellationToken) - { - var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if (orderToUpdate == null) - { - return false; - } - - orderToUpdate.SetCancelledStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); - } + orderToUpdate.SetCancelledStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class CancelOrderIdentifiedCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class CancelOrderIdentifiedCommandHandler : IdentifiedCommandHandler +{ + public CancelOrderIdentifiedCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public CancelOrderIdentifiedCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs index fa7a2f706..fb16306ee 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs @@ -1,106 +1,100 @@ -using MediatR; -using Ordering.API.Application.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +// DDD and CQRS patterns comment: Note that it is recommended to implement immutable Commands +// In this case, its immutability is achieved by having all the setters as private +// plus only being able to update the data just once, when creating the object through its constructor. +// References on Immutable Commands: +// http://cqrs.nu/Faq +// https://docs.spine3.org/motivation/immutability.html +// http://blog.gauffin.org/2012/06/griffin-container-introducing-command-support/ +// https://docs.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties + +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; + +[DataContract] +public class CreateOrderCommand + : IRequest { - // DDD and CQRS patterns comment: Note that it is recommended to implement immutable Commands - // In this case, its immutability is achieved by having all the setters as private - // plus only being able to update the data just once, when creating the object through its constructor. - // References on Immutable Commands: - // http://cqrs.nu/Faq - // https://docs.spine3.org/motivation/immutability.html - // http://blog.gauffin.org/2012/06/griffin-container-introducing-command-support/ - // https://docs.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/how-to-implement-a-lightweight-class-with-auto-implemented-properties - - [DataContract] - public class CreateOrderCommand - : IRequest - { - [DataMember] - private readonly List _orderItems; + [DataMember] + private readonly List _orderItems; - [DataMember] - public string UserId { get; private set; } + [DataMember] + public string UserId { get; private set; } - [DataMember] - public string UserName { get; private set; } + [DataMember] + public string UserName { get; private set; } - [DataMember] - public string City { get; private set; } + [DataMember] + public string City { get; private set; } - [DataMember] - public string Street { get; private set; } + [DataMember] + public string Street { get; private set; } - [DataMember] - public string State { get; private set; } + [DataMember] + public string State { get; private set; } - [DataMember] - public string Country { get; private set; } + [DataMember] + public string Country { get; private set; } - [DataMember] - public string ZipCode { get; private set; } + [DataMember] + public string ZipCode { get; private set; } - [DataMember] - public string CardNumber { get; private set; } + [DataMember] + public string CardNumber { get; private set; } - [DataMember] - public string CardHolderName { get; private set; } + [DataMember] + public string CardHolderName { get; private set; } - [DataMember] - public DateTime CardExpiration { get; private set; } + [DataMember] + public DateTime CardExpiration { get; private set; } - [DataMember] - public string CardSecurityNumber { get; private set; } + [DataMember] + public string CardSecurityNumber { get; private set; } - [DataMember] - public int CardTypeId { get; private set; } + [DataMember] + public int CardTypeId { get; private set; } - [DataMember] - public IEnumerable OrderItems => _orderItems; + [DataMember] + public IEnumerable OrderItems => _orderItems; - public CreateOrderCommand() - { - _orderItems = new List(); - } + public CreateOrderCommand() + { + _orderItems = new List(); + } - public CreateOrderCommand(List basketItems, string userId, string userName, string city, string street, string state, string country, string zipcode, - string cardNumber, string cardHolderName, DateTime cardExpiration, - string cardSecurityNumber, int cardTypeId) : this() - { - _orderItems = basketItems.ToOrderItemsDTO().ToList(); - UserId = userId; - UserName = userName; - City = city; - Street = street; - State = state; - Country = country; - ZipCode = zipcode; - CardNumber = cardNumber; - CardHolderName = cardHolderName; - CardExpiration = cardExpiration; - CardSecurityNumber = cardSecurityNumber; - CardTypeId = cardTypeId; - CardExpiration = cardExpiration; - } + public CreateOrderCommand(List basketItems, string userId, string userName, string city, string street, string state, string country, string zipcode, + string cardNumber, string cardHolderName, DateTime cardExpiration, + string cardSecurityNumber, int cardTypeId) : this() + { + _orderItems = basketItems.ToOrderItemsDTO().ToList(); + UserId = userId; + UserName = userName; + City = city; + Street = street; + State = state; + Country = country; + ZipCode = zipcode; + CardNumber = cardNumber; + CardHolderName = cardHolderName; + CardExpiration = cardExpiration; + CardSecurityNumber = cardSecurityNumber; + CardTypeId = cardTypeId; + } - public record OrderItemDTO - { - public int ProductId { get; init; } + public record OrderItemDTO + { + public int ProductId { get; init; } - public string ProductName { get; init; } + public string ProductName { get; init; } - public decimal UnitPrice { get; init; } + public decimal UnitPrice { get; init; } - public decimal Discount { get; init; } + public decimal Discount { get; init; } - public int Units { get; init; } + public int Units { get; init; } - public string PictureUrl { get; init; } - } + public string PictureUrl { get; init; } } } + diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs index b2fff253d..e445e5de1 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs @@ -1,82 +1,72 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + +// Regular CommandHandler +public class CreateOrderCommandHandler + : IRequestHandler { - using Domain.AggregatesModel.OrderAggregate; - using global::Ordering.API.Application.IntegrationEvents; - using global::Ordering.API.Application.IntegrationEvents.Events; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; - using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; - using Microsoft.Extensions.Logging; - using System; - using System.Threading; - using System.Threading.Tasks; + private readonly IOrderRepository _orderRepository; + private readonly IIdentityService _identityService; + private readonly IMediator _mediator; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + private readonly ILogger _logger; - // Regular CommandHandler - public class CreateOrderCommandHandler - : IRequestHandler + // Using DI to inject infrastructure persistence Repositories + public CreateOrderCommandHandler(IMediator mediator, + IOrderingIntegrationEventService orderingIntegrationEventService, + IOrderRepository orderRepository, + IIdentityService identityService, + ILogger logger) { - private readonly IOrderRepository _orderRepository; - private readonly IIdentityService _identityService; - private readonly IMediator _mediator; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - private readonly ILogger _logger; - - // Using DI to inject infrastructure persistence Repositories - public CreateOrderCommandHandler(IMediator mediator, - IOrderingIntegrationEventService orderingIntegrationEventService, - IOrderRepository orderRepository, - IIdentityService identityService, - ILogger logger) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(CreateOrderCommand message, CancellationToken cancellationToken) - { - // Add Integration event to clean the basket - var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent(message.UserId); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStartedIntegrationEvent); + public async Task Handle(CreateOrderCommand message, CancellationToken cancellationToken) + { + // Add Integration event to clean the basket + var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent(message.UserId); + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStartedIntegrationEvent); - // Add/Update the Buyer AggregateRoot - // DDD patterns comment: Add child entities and value-objects through the Order Aggregate-Root - // methods and constructor so validations, invariants and business logic - // make sure that consistency is preserved across the whole aggregate - var address = new Address(message.Street, message.City, message.State, message.Country, message.ZipCode); - var order = new Order(message.UserId, message.UserName, address, message.CardTypeId, message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration); + // Add/Update the Buyer AggregateRoot + // DDD patterns comment: Add child entities and value-objects through the Order Aggregate-Root + // methods and constructor so validations, invariants and business logic + // make sure that consistency is preserved across the whole aggregate + var address = new Address(message.Street, message.City, message.State, message.Country, message.ZipCode); + var order = new Order(message.UserId, message.UserName, address, message.CardTypeId, message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration); - foreach (var item in message.OrderItems) - { - order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units); - } + foreach (var item in message.OrderItems) + { + order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units); + } - _logger.LogInformation("----- Creating Order - Order: {@Order}", order); + _logger.LogInformation("----- Creating Order - Order: {@Order}", order); - _orderRepository.Add(order); + _orderRepository.Add(order); - return await _orderRepository.UnitOfWork - .SaveEntitiesAsync(cancellationToken); - } + return await _orderRepository.UnitOfWork + .SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class CreateOrderIdentifiedCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class CreateOrderIdentifiedCommandHandler : IdentifiedCommandHandler +{ + public CreateOrderIdentifiedCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public CreateOrderIdentifiedCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for creating order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for creating order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs index bb3e92378..4866212d9 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommand.cs @@ -1,21 +1,16 @@ -using MediatR; -using Ordering.API.Application.Models; -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +public class CreateOrderDraftCommand : IRequest { - public class CreateOrderDraftCommand : IRequest - { - public string BuyerId { get; private set; } + public string BuyerId { get; private set; } - public IEnumerable Items { get; private set; } + public IEnumerable Items { get; private set; } - public CreateOrderDraftCommand(string buyerId, IEnumerable items) - { - BuyerId = buyerId; - Items = items; - } + public CreateOrderDraftCommand(string buyerId, IEnumerable items) + { + BuyerId = buyerId; + Items = items; } - } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs index abca17b8c..32d965fd0 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderDraftCommandHandler.cs @@ -1,71 +1,58 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands -{ - using Domain.AggregatesModel.OrderAggregate; - using global::Ordering.API.Application.Models; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; - - // Regular CommandHandler - public class CreateOrderDraftCommandHandler - : IRequestHandler - { - private readonly IOrderRepository _orderRepository; - private readonly IIdentityService _identityService; - private readonly IMediator _mediator; - - // Using DI to inject infrastructure persistence Repositories - public CreateOrderDraftCommandHandler(IMediator mediator, IIdentityService identityService) - { - _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - } +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; - public Task Handle(CreateOrderDraftCommand message, CancellationToken cancellationToken) - { +using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - var order = Order.NewDraft(); - var orderItems = message.Items.Select(i => i.ToOrderItemDTO()); - foreach (var item in orderItems) - { - order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units); - } +// Regular CommandHandler +public class CreateOrderDraftCommandHandler + : IRequestHandler +{ + private readonly IOrderRepository _orderRepository; + private readonly IIdentityService _identityService; + private readonly IMediator _mediator; - return Task.FromResult(OrderDraftDTO.FromOrder(order)); - } + // Using DI to inject infrastructure persistence Repositories + public CreateOrderDraftCommandHandler(IMediator mediator, IIdentityService identityService) + { + _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); } - - public record OrderDraftDTO + public Task Handle(CreateOrderDraftCommand message, CancellationToken cancellationToken) { - public IEnumerable OrderItems { get; init; } - public decimal Total { get; init; } - public static OrderDraftDTO FromOrder(Order order) + var order = Order.NewDraft(); + var orderItems = message.Items.Select(i => i.ToOrderItemDTO()); + foreach (var item in orderItems) { - return new OrderDraftDTO() - { - OrderItems = order.OrderItems.Select(oi => new OrderItemDTO - { - Discount = oi.GetCurrentDiscount(), - ProductId = oi.ProductId, - UnitPrice = oi.GetUnitPrice(), - PictureUrl = oi.GetPictureUri(), - Units = oi.GetUnits(), - ProductName = oi.GetOrderItemProductName() - }), - Total = order.GetTotal() - }; + order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units); } + return Task.FromResult(OrderDraftDTO.FromOrder(order)); } +} +public record OrderDraftDTO +{ + public IEnumerable OrderItems { get; init; } + public decimal Total { get; init; } + public static OrderDraftDTO FromOrder(Order order) + { + return new OrderDraftDTO() + { + OrderItems = order.OrderItems.Select(oi => new OrderItemDTO + { + Discount = oi.GetCurrentDiscount(), + ProductId = oi.ProductId, + UnitPrice = oi.GetUnitPrice(), + PictureUrl = oi.GetPictureUri(), + Units = oi.GetUnits(), + ProductName = oi.GetOrderItemProductName() + }), + Total = order.GetTotal() + }; + } -} +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs index 9486cd143..5109ced4e 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs @@ -1,17 +1,13 @@ -using MediatR; -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +public class IdentifiedCommand : IRequest + where T : IRequest { - public class IdentifiedCommand : IRequest - where T : IRequest + public T Command { get; } + public Guid Id { get; } + public IdentifiedCommand(T command, Guid id) { - public T Command { get; } - public Guid Id { get; } - public IdentifiedCommand(T command, Guid id) - { - Command = command; - Id = id; - } + Command = command; + Id = id; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs index be94e414c..38c8a356d 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommandHandler.cs @@ -1,116 +1,107 @@ -using MediatR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.Commands; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands +/// +/// Provides a base implementation for handling duplicate request and ensuring idempotent updates, in the cases where +/// a requestid sent by client is used to detect duplicate requests. +/// +/// Type of the command handler that performs the operation if request is not duplicated +/// Return value of the inner command handler +public class IdentifiedCommandHandler : IRequestHandler, R> + where T : IRequest { + private readonly IMediator _mediator; + private readonly IRequestManager _requestManager; + private readonly ILogger> _logger; + + public IdentifiedCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + { + _mediator = mediator; + _requestManager = requestManager; + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + } + /// - /// Provides a base implementation for handling duplicate request and ensuring idempotent updates, in the cases where - /// a requestid sent by client is used to detect duplicate requests. + /// Creates the result value to return if a previous request was found /// - /// Type of the command handler that performs the operation if request is not duplicated - /// Return value of the inner command handler - public class IdentifiedCommandHandler : IRequestHandler, R> - where T : IRequest + /// + protected virtual R CreateResultForDuplicateRequest() { - private readonly IMediator _mediator; - private readonly IRequestManager _requestManager; - private readonly ILogger> _logger; - - public IdentifiedCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - { - _mediator = mediator; - _requestManager = requestManager; - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - } + return default(R); + } - /// - /// Creates the result value to return if a previous request was found - /// - /// - protected virtual R CreateResultForDuplicateRequest() + /// + /// This method handles the command. It just ensures that no other request exists with the same ID, and if this is the case + /// just enqueues the original inner command. + /// + /// IdentifiedCommand which contains both original command & request ID + /// Return value of inner command or default value if request same ID was found + public async Task Handle(IdentifiedCommand message, CancellationToken cancellationToken) + { + var alreadyExists = await _requestManager.ExistAsync(message.Id); + if (alreadyExists) { - return default(R); + return CreateResultForDuplicateRequest(); } - - /// - /// This method handles the command. It just ensures that no other request exists with the same ID, and if this is the case - /// just enqueues the original inner command. - /// - /// IdentifiedCommand which contains both original command & request ID - /// Return value of inner command or default value if request same ID was found - public async Task Handle(IdentifiedCommand message, CancellationToken cancellationToken) + else { - var alreadyExists = await _requestManager.ExistAsync(message.Id); - if (alreadyExists) - { - return CreateResultForDuplicateRequest(); - } - else + await _requestManager.CreateRequestForCommandAsync(message.Id); + try { - await _requestManager.CreateRequestForCommandAsync(message.Id); - try - { - var command = message.Command; - var commandName = command.GetGenericTypeName(); - var idProperty = string.Empty; - var commandId = string.Empty; + var command = message.Command; + var commandName = command.GetGenericTypeName(); + var idProperty = string.Empty; + var commandId = string.Empty; - switch (command) - { - case CreateOrderCommand createOrderCommand: - idProperty = nameof(createOrderCommand.UserId); - commandId = createOrderCommand.UserId; - break; + switch (command) + { + case CreateOrderCommand createOrderCommand: + idProperty = nameof(createOrderCommand.UserId); + commandId = createOrderCommand.UserId; + break; - case CancelOrderCommand cancelOrderCommand: - idProperty = nameof(cancelOrderCommand.OrderNumber); - commandId = $"{cancelOrderCommand.OrderNumber}"; - break; + case CancelOrderCommand cancelOrderCommand: + idProperty = nameof(cancelOrderCommand.OrderNumber); + commandId = $"{cancelOrderCommand.OrderNumber}"; + break; - case ShipOrderCommand shipOrderCommand: - idProperty = nameof(shipOrderCommand.OrderNumber); - commandId = $"{shipOrderCommand.OrderNumber}"; - break; + case ShipOrderCommand shipOrderCommand: + idProperty = nameof(shipOrderCommand.OrderNumber); + commandId = $"{shipOrderCommand.OrderNumber}"; + break; - default: - idProperty = "Id?"; - commandId = "n/a"; - break; - } + default: + idProperty = "Id?"; + commandId = "n/a"; + break; + } - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - commandName, - idProperty, - commandId, - command); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + commandName, + idProperty, + commandId, + command); - // Send the embeded business command to mediator so it runs its related CommandHandler - var result = await _mediator.Send(command, cancellationToken); + // Send the embeded business command to mediator so it runs its related CommandHandler + var result = await _mediator.Send(command, cancellationToken); - _logger.LogInformation( - "----- Command result: {@Result} - {CommandName} - {IdProperty}: {CommandId} ({@Command})", - result, - commandName, - idProperty, - commandId, - command); + _logger.LogInformation( + "----- Command result: {@Result} - {CommandName} - {IdProperty}: {CommandId} ({@Command})", + result, + commandName, + idProperty, + commandId, + command); - return result; - } - catch - { - return default(R); - } + return result; + } + catch + { + return default(R); } } } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs index 980211f87..99337f13e 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs @@ -1,17 +1,13 @@ -using MediatR; -using System.Runtime.Serialization; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +public class SetAwaitingValidationOrderStatusCommand : IRequest { - public class SetAwaitingValidationOrderStatusCommand : IRequest - { - [DataMember] - public int OrderNumber { get; private set; } + [DataMember] + public int OrderNumber { get; private set; } - public SetAwaitingValidationOrderStatusCommand(int orderNumber) - { - OrderNumber = orderNumber; - } + public SetAwaitingValidationOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs index da6969404..c8bd37d75 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs @@ -1,57 +1,48 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +// Regular CommandHandler +public class SetAwaitingValidationOrderStatusCommandHandler : IRequestHandler { - // Regular CommandHandler - public class SetAwaitingValidationOrderStatusCommandHandler : IRequestHandler + private readonly IOrderRepository _orderRepository; + + public SetAwaitingValidationOrderStatusCommandHandler(IOrderRepository orderRepository) { - private readonly IOrderRepository _orderRepository; + _orderRepository = orderRepository; + } - public SetAwaitingValidationOrderStatusCommandHandler(IOrderRepository orderRepository) + /// + /// Handler which processes the command when + /// graceperiod has finished + /// + /// + /// + public async Task Handle(SetAwaitingValidationOrderStatusCommand command, CancellationToken cancellationToken) + { + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if (orderToUpdate == null) { - _orderRepository = orderRepository; + return false; } - /// - /// Handler which processes the command when - /// graceperiod has finished - /// - /// - /// - public async Task Handle(SetAwaitingValidationOrderStatusCommand command, CancellationToken cancellationToken) - { - var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if (orderToUpdate == null) - { - return false; - } - - orderToUpdate.SetAwaitingValidationStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); - } + orderToUpdate.SetAwaitingValidationStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class SetAwaitingValidationIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class SetAwaitingValidationIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler +{ + public SetAwaitingValidationIdentifiedOrderStatusCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public SetAwaitingValidationIdentifiedOrderStatusCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs index d561ad7f3..0e95aac8d 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs @@ -1,17 +1,13 @@ -using MediatR; -using System.Runtime.Serialization; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +public class SetPaidOrderStatusCommand : IRequest { - public class SetPaidOrderStatusCommand : IRequest - { - [DataMember] - public int OrderNumber { get; private set; } + [DataMember] + public int OrderNumber { get; private set; } - public SetPaidOrderStatusCommand(int orderNumber) - { - OrderNumber = orderNumber; - } + public SetPaidOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs index f4268e9ca..09520a65f 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs @@ -1,60 +1,51 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; - -namespace Ordering.API.Application.Commands +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +// Regular CommandHandler +public class SetPaidOrderStatusCommandHandler : IRequestHandler { - // Regular CommandHandler - public class SetPaidOrderStatusCommandHandler : IRequestHandler + private readonly IOrderRepository _orderRepository; + + public SetPaidOrderStatusCommandHandler(IOrderRepository orderRepository) { - private readonly IOrderRepository _orderRepository; + _orderRepository = orderRepository; + } - public SetPaidOrderStatusCommandHandler(IOrderRepository orderRepository) - { - _orderRepository = orderRepository; - } + /// + /// Handler which processes the command when + /// Shipment service confirms the payment + /// + /// + /// + public async Task Handle(SetPaidOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for validating the payment + await Task.Delay(10000, cancellationToken); - /// - /// Handler which processes the command when - /// Shipment service confirms the payment - /// - /// - /// - public async Task Handle(SetPaidOrderStatusCommand command, CancellationToken cancellationToken) + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if (orderToUpdate == null) { - // Simulate a work time for validating the payment - await Task.Delay(10000, cancellationToken); - - var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if (orderToUpdate == null) - { - return false; - } - - orderToUpdate.SetPaidStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + return false; } + + orderToUpdate.SetPaidStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class SetPaidIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class SetPaidIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler +{ + public SetPaidIdentifiedOrderStatusCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public SetPaidIdentifiedOrderStatusCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs index 9e0a40915..b4883ec49 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs @@ -1,17 +1,13 @@ -using MediatR; -using System.Runtime.Serialization; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +public class SetStockConfirmedOrderStatusCommand : IRequest { - public class SetStockConfirmedOrderStatusCommand : IRequest - { - [DataMember] - public int OrderNumber { get; private set; } + [DataMember] + public int OrderNumber { get; private set; } - public SetStockConfirmedOrderStatusCommand(int orderNumber) - { - OrderNumber = orderNumber; - } + public SetStockConfirmedOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs index c99daa23a..df87db63c 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs @@ -1,60 +1,51 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; - -namespace Ordering.API.Application.Commands +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +// Regular CommandHandler +public class SetStockConfirmedOrderStatusCommandHandler : IRequestHandler { - // Regular CommandHandler - public class SetStockConfirmedOrderStatusCommandHandler : IRequestHandler + private readonly IOrderRepository _orderRepository; + + public SetStockConfirmedOrderStatusCommandHandler(IOrderRepository orderRepository) { - private readonly IOrderRepository _orderRepository; + _orderRepository = orderRepository; + } - public SetStockConfirmedOrderStatusCommandHandler(IOrderRepository orderRepository) - { - _orderRepository = orderRepository; - } + /// + /// Handler which processes the command when + /// Stock service confirms the request + /// + /// + /// + public async Task Handle(SetStockConfirmedOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for confirming the stock + await Task.Delay(10000, cancellationToken); - /// - /// Handler which processes the command when - /// Stock service confirms the request - /// - /// - /// - public async Task Handle(SetStockConfirmedOrderStatusCommand command, CancellationToken cancellationToken) + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if (orderToUpdate == null) { - // Simulate a work time for confirming the stock - await Task.Delay(10000, cancellationToken); - - var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if (orderToUpdate == null) - { - return false; - } - - orderToUpdate.SetStockConfirmedStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); + return false; } + + orderToUpdate.SetStockConfirmedStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class SetStockConfirmedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class SetStockConfirmedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler +{ + public SetStockConfirmedOrderStatusIdenfifiedCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public SetStockConfirmedOrderStatusIdenfifiedCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs index cb39c5567..e8b3cac4d 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs @@ -1,22 +1,17 @@ -using MediatR; -using System.Collections.Generic; -using System.Runtime.Serialization; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +public class SetStockRejectedOrderStatusCommand : IRequest { - public class SetStockRejectedOrderStatusCommand : IRequest - { - [DataMember] - public int OrderNumber { get; private set; } + [DataMember] + public int OrderNumber { get; private set; } - [DataMember] - public List OrderStockItems { get; private set; } + [DataMember] + public List OrderStockItems { get; private set; } - public SetStockRejectedOrderStatusCommand(int orderNumber, List orderStockItems) - { - OrderNumber = orderNumber; - OrderStockItems = orderStockItems; - } + public SetStockRejectedOrderStatusCommand(int orderNumber, List orderStockItems) + { + OrderNumber = orderNumber; + OrderStockItems = orderStockItems; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs index 551b2744d..fcef729e6 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs @@ -1,61 +1,52 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; - -namespace Ordering.API.Application.Commands +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +// Regular CommandHandler +public class SetStockRejectedOrderStatusCommandHandler : IRequestHandler { - // Regular CommandHandler - public class SetStockRejectedOrderStatusCommandHandler : IRequestHandler + private readonly IOrderRepository _orderRepository; + + public SetStockRejectedOrderStatusCommandHandler(IOrderRepository orderRepository) { - private readonly IOrderRepository _orderRepository; + _orderRepository = orderRepository; + } - public SetStockRejectedOrderStatusCommandHandler(IOrderRepository orderRepository) - { - _orderRepository = orderRepository; - } + /// + /// Handler which processes the command when + /// Stock service rejects the request + /// + /// + /// + public async Task Handle(SetStockRejectedOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for rejecting the stock + await Task.Delay(10000, cancellationToken); - /// - /// Handler which processes the command when - /// Stock service rejects the request - /// - /// - /// - public async Task Handle(SetStockRejectedOrderStatusCommand command, CancellationToken cancellationToken) + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if (orderToUpdate == null) { - // Simulate a work time for rejecting the stock - await Task.Delay(10000, cancellationToken); - - var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if (orderToUpdate == null) - { - return false; - } + return false; + } - orderToUpdate.SetCancelledStatusWhenStockIsRejected(command.OrderStockItems); + orderToUpdate.SetCancelledStatusWhenStockIsRejected(command.OrderStockItems); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); - } + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class SetStockRejectedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class SetStockRejectedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler +{ + public SetStockRejectedOrderStatusIdenfifiedCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public SetStockRejectedOrderStatusIdenfifiedCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs index e267e6b66..c8fecde2b 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommand.cs @@ -1,17 +1,13 @@ -using MediatR; -using System.Runtime.Serialization; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +public class ShipOrderCommand : IRequest { - public class ShipOrderCommand : IRequest - { - [DataMember] - public int OrderNumber { get; private set; } + [DataMember] + public int OrderNumber { get; private set; } - public ShipOrderCommand(int orderNumber) - { - OrderNumber = orderNumber; - } + public ShipOrderCommand(int orderNumber) + { + OrderNumber = orderNumber; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs index 4e1173c05..58b09f53b 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/ShipOrderCommandHandler.cs @@ -1,57 +1,48 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.Extensions.Logging; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -namespace Ordering.API.Application.Commands +// Regular CommandHandler +public class ShipOrderCommandHandler : IRequestHandler { - // Regular CommandHandler - public class ShipOrderCommandHandler : IRequestHandler + private readonly IOrderRepository _orderRepository; + + public ShipOrderCommandHandler(IOrderRepository orderRepository) { - private readonly IOrderRepository _orderRepository; + _orderRepository = orderRepository; + } - public ShipOrderCommandHandler(IOrderRepository orderRepository) + /// + /// Handler which processes the command when + /// administrator executes ship order from app + /// + /// + /// + public async Task Handle(ShipOrderCommand command, CancellationToken cancellationToken) + { + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if (orderToUpdate == null) { - _orderRepository = orderRepository; + return false; } - /// - /// Handler which processes the command when - /// administrator executes ship order from app - /// - /// - /// - public async Task Handle(ShipOrderCommand command, CancellationToken cancellationToken) - { - var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); - if (orderToUpdate == null) - { - return false; - } - - orderToUpdate.SetShippedStatus(); - return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); - } + orderToUpdate.SetShippedStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); } +} - // Use for Idempotency in Command process - public class ShipOrderIdentifiedCommandHandler : IdentifiedCommandHandler +// Use for Idempotency in Command process +public class ShipOrderIdentifiedCommandHandler : IdentifiedCommandHandler +{ + public ShipOrderIdentifiedCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) { - public ShipOrderIdentifiedCommandHandler( - IMediator mediator, - IRequestManager requestManager, - ILogger> logger) - : base(mediator, requestManager, logger) - { - } + } - protected override bool CreateResultForDuplicateRequest() - { - return true; // Ignore duplicate requests for processing order. - } + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. } } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs index bea8eaac5..919a78a45 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs @@ -1,38 +1,29 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.Extensions.Logging; -using Ordering.Domain.Events; -using System; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVerified; -namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVerified +public class UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler + : INotificationHandler { - public class UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler - : INotificationHandler - { - private readonly IOrderRepository _orderRepository; - private readonly ILoggerFactory _logger; + private readonly IOrderRepository _orderRepository; + private readonly ILoggerFactory _logger; - public UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler( - IOrderRepository orderRepository, ILoggerFactory logger) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler( + IOrderRepository orderRepository, ILoggerFactory logger) + { + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - // Domain Logic comment: - // When the Buyer and Buyer's payment method have been created or verified that they existed, - // then we can update the original Order with the BuyerId and PaymentId (foreign keys) - public async Task Handle(BuyerAndPaymentMethodVerifiedDomainEvent buyerPaymentMethodVerifiedEvent, CancellationToken cancellationToken) - { - var orderToUpdate = await _orderRepository.GetAsync(buyerPaymentMethodVerifiedEvent.OrderId); - orderToUpdate.SetBuyerId(buyerPaymentMethodVerifiedEvent.Buyer.Id); - orderToUpdate.SetPaymentId(buyerPaymentMethodVerifiedEvent.Payment.Id); + // Domain Logic comment: + // When the Buyer and Buyer's payment method have been created or verified that they existed, + // then we can update the original Order with the BuyerId and PaymentId (foreign keys) + public async Task Handle(BuyerAndPaymentMethodVerifiedDomainEvent buyerPaymentMethodVerifiedEvent, CancellationToken cancellationToken) + { + var orderToUpdate = await _orderRepository.GetAsync(buyerPaymentMethodVerifiedEvent.OrderId); + orderToUpdate.SetBuyerId(buyerPaymentMethodVerifiedEvent.Buyer.Id); + orderToUpdate.SetPaymentId(buyerPaymentMethodVerifiedEvent.Payment.Id); - _logger.CreateLogger() - .LogTrace("Order with Id: {OrderId} has been successfully updated with a payment method {PaymentMethod} ({Id})", - buyerPaymentMethodVerifiedEvent.OrderId, nameof(buyerPaymentMethodVerifiedEvent.Payment), buyerPaymentMethodVerifiedEvent.Payment.Id); - } + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated with a payment method {PaymentMethod} ({Id})", + buyerPaymentMethodVerifiedEvent.OrderId, nameof(buyerPaymentMethodVerifiedEvent.Payment), buyerPaymentMethodVerifiedEvent.Payment.Id); } } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs index f8fddf3a8..dbd8abceb 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCancelled/OrderCancelledDomainEventHandler.cs @@ -1,47 +1,37 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.IntegrationEvents; -using Ordering.API.Application.IntegrationEvents.Events; -using Ordering.Domain.Events; -using System; -using System.Threading; -using System.Threading.Tasks; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; -namespace Ordering.API.Application.DomainEventHandlers.OrderCancelled +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderCancelled; + +public class OrderCancelledDomainEventHandler + : INotificationHandler { - public class OrderCancelledDomainEventHandler - : INotificationHandler - { - private readonly IOrderRepository _orderRepository; - private readonly IBuyerRepository _buyerRepository; - private readonly ILoggerFactory _logger; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + private readonly IOrderRepository _orderRepository; + private readonly IBuyerRepository _buyerRepository; + private readonly ILoggerFactory _logger; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - public OrderCancelledDomainEventHandler( - IOrderRepository orderRepository, - ILoggerFactory logger, - IBuyerRepository buyerRepository, - IOrderingIntegrationEventService orderingIntegrationEventService) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); - _orderingIntegrationEventService = orderingIntegrationEventService; - } + public OrderCancelledDomainEventHandler( + IOrderRepository orderRepository, + ILoggerFactory logger, + IBuyerRepository buyerRepository, + IOrderingIntegrationEventService orderingIntegrationEventService) + { + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); + _orderingIntegrationEventService = orderingIntegrationEventService; + } - public async Task Handle(OrderCancelledDomainEvent orderCancelledDomainEvent, CancellationToken cancellationToken) - { - _logger.CreateLogger() - .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", - orderCancelledDomainEvent.Order.Id, nameof(OrderStatus.Cancelled), OrderStatus.Cancelled.Id); + public async Task Handle(OrderCancelledDomainEvent orderCancelledDomainEvent, CancellationToken cancellationToken) + { + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", + orderCancelledDomainEvent.Order.Id, nameof(OrderStatus.Cancelled), OrderStatus.Cancelled.Id); - var order = await _orderRepository.GetAsync(orderCancelledDomainEvent.Order.Id); - var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); + var order = await _orderRepository.GetAsync(orderCancelledDomainEvent.Order.Id); + var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); - var orderStatusChangedToCancelledIntegrationEvent = new OrderStatusChangedToCancelledIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToCancelledIntegrationEvent); - } + var orderStatusChangedToCancelledIntegrationEvent = new OrderStatusChangedToCancelledIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToCancelledIntegrationEvent); } } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs index 82904fdd7..2aa3867be 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderGracePeriodConfirmed/OrderStatusChangedToAwaitingValidationDomainEventHandler.cs @@ -1,52 +1,39 @@ -namespace Ordering.API.Application.DomainEventHandlers.OrderGracePeriodConfirmed +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderGracePeriodConfirmed; + +public class OrderStatusChangedToAwaitingValidationDomainEventHandler + : INotificationHandler { - using Domain.Events; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.IntegrationEvents; - using Ordering.API.Application.IntegrationEvents.Events; - using System; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; + private readonly IOrderRepository _orderRepository; + private readonly ILoggerFactory _logger; + private readonly IBuyerRepository _buyerRepository; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - public class OrderStatusChangedToAwaitingValidationDomainEventHandler - : INotificationHandler + public OrderStatusChangedToAwaitingValidationDomainEventHandler( + IOrderRepository orderRepository, ILoggerFactory logger, + IBuyerRepository buyerRepository, + IOrderingIntegrationEventService orderingIntegrationEventService) { - private readonly IOrderRepository _orderRepository; - private readonly ILoggerFactory _logger; - private readonly IBuyerRepository _buyerRepository; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - - public OrderStatusChangedToAwaitingValidationDomainEventHandler( - IOrderRepository orderRepository, ILoggerFactory logger, - IBuyerRepository buyerRepository, - IOrderingIntegrationEventService orderingIntegrationEventService) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _buyerRepository = buyerRepository; - _orderingIntegrationEventService = orderingIntegrationEventService; - } + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _buyerRepository = buyerRepository; + _orderingIntegrationEventService = orderingIntegrationEventService; + } - public async Task Handle(OrderStatusChangedToAwaitingValidationDomainEvent orderStatusChangedToAwaitingValidationDomainEvent, CancellationToken cancellationToken) - { - _logger.CreateLogger() - .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", - orderStatusChangedToAwaitingValidationDomainEvent.OrderId, nameof(OrderStatus.AwaitingValidation), OrderStatus.AwaitingValidation.Id); + public async Task Handle(OrderStatusChangedToAwaitingValidationDomainEvent orderStatusChangedToAwaitingValidationDomainEvent, CancellationToken cancellationToken) + { + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", + orderStatusChangedToAwaitingValidationDomainEvent.OrderId, nameof(OrderStatus.AwaitingValidation), OrderStatus.AwaitingValidation.Id); - var order = await _orderRepository.GetAsync(orderStatusChangedToAwaitingValidationDomainEvent.OrderId); + var order = await _orderRepository.GetAsync(orderStatusChangedToAwaitingValidationDomainEvent.OrderId); - var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); + var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); - var orderStockList = orderStatusChangedToAwaitingValidationDomainEvent.OrderItems - .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); + var orderStockList = orderStatusChangedToAwaitingValidationDomainEvent.OrderItems + .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); - var orderStatusChangedToAwaitingValidationIntegrationEvent = new OrderStatusChangedToAwaitingValidationIntegrationEvent( - order.Id, order.OrderStatus.Name, buyer.Name, orderStockList); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToAwaitingValidationIntegrationEvent); - } + var orderStatusChangedToAwaitingValidationIntegrationEvent = new OrderStatusChangedToAwaitingValidationIntegrationEvent( + order.Id, order.OrderStatus.Name, buyer.Name, orderStockList); + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToAwaitingValidationIntegrationEvent); } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs index fac62e7e2..7f0138d71 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderPaid/OrderStatusChangedToPaidDomainEventHandler.cs @@ -1,57 +1,44 @@ -namespace Ordering.API.Application.DomainEventHandlers.OrderPaid +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderPaid; + +public class OrderStatusChangedToPaidDomainEventHandler + : INotificationHandler { - using Domain.Events; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.IntegrationEvents; - using Ordering.API.Application.IntegrationEvents.Events; - using System; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - - public class OrderStatusChangedToPaidDomainEventHandler - : INotificationHandler - { - private readonly IOrderRepository _orderRepository; - private readonly ILoggerFactory _logger; - private readonly IBuyerRepository _buyerRepository; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + private readonly IOrderRepository _orderRepository; + private readonly ILoggerFactory _logger; + private readonly IBuyerRepository _buyerRepository; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - public OrderStatusChangedToPaidDomainEventHandler( - IOrderRepository orderRepository, ILoggerFactory logger, - IBuyerRepository buyerRepository, - IOrderingIntegrationEventService orderingIntegrationEventService - ) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); - _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); - } + public OrderStatusChangedToPaidDomainEventHandler( + IOrderRepository orderRepository, ILoggerFactory logger, + IBuyerRepository buyerRepository, + IOrderingIntegrationEventService orderingIntegrationEventService + ) + { + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); + _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); + } - public async Task Handle(OrderStatusChangedToPaidDomainEvent orderStatusChangedToPaidDomainEvent, CancellationToken cancellationToken) - { - _logger.CreateLogger() - .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", - orderStatusChangedToPaidDomainEvent.OrderId, nameof(OrderStatus.Paid), OrderStatus.Paid.Id); + public async Task Handle(OrderStatusChangedToPaidDomainEvent orderStatusChangedToPaidDomainEvent, CancellationToken cancellationToken) + { + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", + orderStatusChangedToPaidDomainEvent.OrderId, nameof(OrderStatus.Paid), OrderStatus.Paid.Id); - var order = await _orderRepository.GetAsync(orderStatusChangedToPaidDomainEvent.OrderId); - var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); + var order = await _orderRepository.GetAsync(orderStatusChangedToPaidDomainEvent.OrderId); + var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); - var orderStockList = orderStatusChangedToPaidDomainEvent.OrderItems - .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); + var orderStockList = orderStatusChangedToPaidDomainEvent.OrderItems + .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); - var orderStatusChangedToPaidIntegrationEvent = new OrderStatusChangedToPaidIntegrationEvent( - orderStatusChangedToPaidDomainEvent.OrderId, - order.OrderStatus.Name, - buyer.Name, - orderStockList); + var orderStatusChangedToPaidIntegrationEvent = new OrderStatusChangedToPaidIntegrationEvent( + orderStatusChangedToPaidDomainEvent.OrderId, + order.OrderStatus.Name, + buyer.Name, + orderStockList); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToPaidIntegrationEvent); - } + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToPaidIntegrationEvent); } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs index 57478c1aa..445c7e04f 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderShipped/OrderShippedDomainEventHandler.cs @@ -1,47 +1,35 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.IntegrationEvents; -using Ordering.API.Application.IntegrationEvents.Events; -using Ordering.Domain.Events; -using System; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderShipped; -namespace Ordering.API.Application.DomainEventHandlers.OrderShipped +public class OrderShippedDomainEventHandler + : INotificationHandler { - public class OrderShippedDomainEventHandler - : INotificationHandler - { - private readonly IOrderRepository _orderRepository; - private readonly IBuyerRepository _buyerRepository; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - private readonly ILoggerFactory _logger; + private readonly IOrderRepository _orderRepository; + private readonly IBuyerRepository _buyerRepository; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + private readonly ILoggerFactory _logger; - public OrderShippedDomainEventHandler( - IOrderRepository orderRepository, - ILoggerFactory logger, - IBuyerRepository buyerRepository, - IOrderingIntegrationEventService orderingIntegrationEventService) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); - _orderingIntegrationEventService = orderingIntegrationEventService; - } + public OrderShippedDomainEventHandler( + IOrderRepository orderRepository, + ILoggerFactory logger, + IBuyerRepository buyerRepository, + IOrderingIntegrationEventService orderingIntegrationEventService) + { + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); + _orderingIntegrationEventService = orderingIntegrationEventService; + } - public async Task Handle(OrderShippedDomainEvent orderShippedDomainEvent, CancellationToken cancellationToken) - { - _logger.CreateLogger() - .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", - orderShippedDomainEvent.Order.Id, nameof(OrderStatus.Shipped), OrderStatus.Shipped.Id); + public async Task Handle(OrderShippedDomainEvent orderShippedDomainEvent, CancellationToken cancellationToken) + { + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", + orderShippedDomainEvent.Order.Id, nameof(OrderStatus.Shipped), OrderStatus.Shipped.Id); - var order = await _orderRepository.GetAsync(orderShippedDomainEvent.Order.Id); - var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); + var order = await _orderRepository.GetAsync(orderShippedDomainEvent.Order.Id); + var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); - var orderStatusChangedToShippedIntegrationEvent = new OrderStatusChangedToShippedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToShippedIntegrationEvent); - } + var orderStatusChangedToShippedIntegrationEvent = new OrderStatusChangedToShippedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToShippedIntegrationEvent); } } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/SendEmailToCustomerWhenOrderStartedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/SendEmailToCustomerWhenOrderStartedDomainEventHandler.cs index 14fa36615..720b656d6 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/SendEmailToCustomerWhenOrderStartedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/SendEmailToCustomerWhenOrderStartedDomainEventHandler.cs @@ -1,16 +1,15 @@ -namespace Ordering.API.Application.DomainEventHandlers.OrderStartedEvent +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderStartedEvent; + +public class SendEmailToCustomerWhenOrderStartedDomainEventHandler +//: IAsyncNotificationHandler { - public class SendEmailToCustomerWhenOrderStartedDomainEventHandler - //: IAsyncNotificationHandler + public SendEmailToCustomerWhenOrderStartedDomainEventHandler() { - public SendEmailToCustomerWhenOrderStartedDomainEventHandler() - { - - } - //public async Task Handle(OrderStartedDomainEvent orderNotification) - //{ - // //TBD - Send email logic - //} } + + //public async Task Handle(OrderStartedDomainEvent orderNotification) + //{ + // //TBD - Send email logic + //} } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs index 44e8ffcf7..da5037259 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStartedEvent/ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler.cs @@ -1,67 +1,55 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.IntegrationEvents; -using Ordering.API.Application.IntegrationEvents.Events; -using Ordering.Domain.Events; -using System; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderStartedEvent; -namespace Ordering.API.Application.DomainEventHandlers.OrderStartedEvent +public class ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler + : INotificationHandler { - public class ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler - : INotificationHandler + private readonly ILoggerFactory _logger; + private readonly IBuyerRepository _buyerRepository; + private readonly IIdentityService _identityService; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + + public ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler( + ILoggerFactory logger, + IBuyerRepository buyerRepository, + IIdentityService identityService, + IOrderingIntegrationEventService orderingIntegrationEventService) { - private readonly ILoggerFactory _logger; - private readonly IBuyerRepository _buyerRepository; - private readonly IIdentityService _identityService; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); + _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); + _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler( - ILoggerFactory logger, - IBuyerRepository buyerRepository, - IIdentityService identityService, - IOrderingIntegrationEventService orderingIntegrationEventService) - { - _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); - _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); - _orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public async Task Handle(OrderStartedDomainEvent orderStartedEvent, CancellationToken cancellationToken) + { + var cardTypeId = (orderStartedEvent.CardTypeId != 0) ? orderStartedEvent.CardTypeId : 1; + var buyer = await _buyerRepository.FindAsync(orderStartedEvent.UserId); + bool buyerOriginallyExisted = (buyer == null) ? false : true; - public async Task Handle(OrderStartedDomainEvent orderStartedEvent, CancellationToken cancellationToken) + if (!buyerOriginallyExisted) { - var cardTypeId = (orderStartedEvent.CardTypeId != 0) ? orderStartedEvent.CardTypeId : 1; - var buyer = await _buyerRepository.FindAsync(orderStartedEvent.UserId); - bool buyerOriginallyExisted = (buyer == null) ? false : true; - - if (!buyerOriginallyExisted) - { - buyer = new Buyer(orderStartedEvent.UserId, orderStartedEvent.UserName); - } - - buyer.VerifyOrAddPaymentMethod(cardTypeId, - $"Payment Method on {DateTime.UtcNow}", - orderStartedEvent.CardNumber, - orderStartedEvent.CardSecurityNumber, - orderStartedEvent.CardHolderName, - orderStartedEvent.CardExpiration, - orderStartedEvent.Order.Id); - - var buyerUpdated = buyerOriginallyExisted ? - _buyerRepository.Update(buyer) : - _buyerRepository.Add(buyer); - - await _buyerRepository.UnitOfWork - .SaveEntitiesAsync(cancellationToken); - - var orderStatusChangedTosubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedTosubmittedIntegrationEvent); - _logger.CreateLogger() - .LogTrace("Buyer {BuyerId} and related payment method were validated or updated for orderId: {OrderId}.", - buyerUpdated.Id, orderStartedEvent.Order.Id); + buyer = new Buyer(orderStartedEvent.UserId, orderStartedEvent.UserName); } + + buyer.VerifyOrAddPaymentMethod(cardTypeId, + $"Payment Method on {DateTime.UtcNow}", + orderStartedEvent.CardNumber, + orderStartedEvent.CardSecurityNumber, + orderStartedEvent.CardHolderName, + orderStartedEvent.CardExpiration, + orderStartedEvent.Order.Id); + + var buyerUpdated = buyerOriginallyExisted ? + _buyerRepository.Update(buyer) : + _buyerRepository.Add(buyer); + + await _buyerRepository.UnitOfWork + .SaveEntitiesAsync(cancellationToken); + + var orderStatusChangedToSubmittedIntegrationEvent = new OrderStatusChangedToSubmittedIntegrationEvent(orderStartedEvent.Order.Id, orderStartedEvent.Order.OrderStatus.Name, buyer.Name); + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToSubmittedIntegrationEvent); + _logger.CreateLogger() + .LogTrace("Buyer {BuyerId} and related payment method were validated or updated for orderId: {OrderId}.", + buyerUpdated.Id, orderStartedEvent.Order.Id); } } diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs index eaad5f2d6..142b6449d 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmed/OrderStatusChangedToStockConfirmedDomainEventHandler.cs @@ -1,47 +1,35 @@ -namespace Ordering.API.Application.DomainEventHandlers.OrderStockConfirmed +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderStockConfirmed; + +public class OrderStatusChangedToStockConfirmedDomainEventHandler + : INotificationHandler { - using Domain.Events; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.IntegrationEvents; - using Ordering.API.Application.IntegrationEvents.Events; - using System; - using System.Threading; - using System.Threading.Tasks; + private readonly IOrderRepository _orderRepository; + private readonly IBuyerRepository _buyerRepository; + private readonly ILoggerFactory _logger; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - public class OrderStatusChangedToStockConfirmedDomainEventHandler - : INotificationHandler + public OrderStatusChangedToStockConfirmedDomainEventHandler( + IOrderRepository orderRepository, + IBuyerRepository buyerRepository, + ILoggerFactory logger, + IOrderingIntegrationEventService orderingIntegrationEventService) { - private readonly IOrderRepository _orderRepository; - private readonly IBuyerRepository _buyerRepository; - private readonly ILoggerFactory _logger; - private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; - - public OrderStatusChangedToStockConfirmedDomainEventHandler( - IOrderRepository orderRepository, - IBuyerRepository buyerRepository, - ILoggerFactory logger, - IOrderingIntegrationEventService orderingIntegrationEventService) - { - _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); - _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _orderingIntegrationEventService = orderingIntegrationEventService; - } + _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); + _buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _orderingIntegrationEventService = orderingIntegrationEventService; + } - public async Task Handle(OrderStatusChangedToStockConfirmedDomainEvent orderStatusChangedToStockConfirmedDomainEvent, CancellationToken cancellationToken) - { - _logger.CreateLogger() - .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", - orderStatusChangedToStockConfirmedDomainEvent.OrderId, nameof(OrderStatus.StockConfirmed), OrderStatus.StockConfirmed.Id); + public async Task Handle(OrderStatusChangedToStockConfirmedDomainEvent orderStatusChangedToStockConfirmedDomainEvent, CancellationToken cancellationToken) + { + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", + orderStatusChangedToStockConfirmedDomainEvent.OrderId, nameof(OrderStatus.StockConfirmed), OrderStatus.StockConfirmed.Id); - var order = await _orderRepository.GetAsync(orderStatusChangedToStockConfirmedDomainEvent.OrderId); - var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); + var order = await _orderRepository.GetAsync(orderStatusChangedToStockConfirmedDomainEvent.OrderId); + var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); - var orderStatusChangedToStockConfirmedIntegrationEvent = new OrderStatusChangedToStockConfirmedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); - await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToStockConfirmedIntegrationEvent); - } + var orderStatusChangedToStockConfirmedIntegrationEvent = new OrderStatusChangedToStockConfirmedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToStockConfirmedIntegrationEvent); } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs index e503695c7..55a8a39b9 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs @@ -1,52 +1,42 @@ -using MediatR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.Commands; -using Ordering.API.Application.IntegrationEvents.Events; -using Serilog.Context; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; -namespace Ordering.API.Application.IntegrationEvents.EventHandling +public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler { - public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IMediator _mediator; - private readonly ILogger _logger; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public GracePeriodConfirmedIntegrationEventHandler( - IMediator mediator, - ILogger logger) - { - _mediator = mediator; - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - } + public GracePeriodConfirmedIntegrationEventHandler( + IMediator mediator, + ILogger logger) + { + _mediator = mediator; + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + } - /// - /// Event handler which confirms that the grace period - /// has been completed and order will not initially be cancelled. - /// Therefore, the order process continues for validation. - /// - /// - /// - /// - public async Task Handle(GracePeriodConfirmedIntegrationEvent @event) + /// + /// Event handler which confirms that the grace period + /// has been completed and order will not initially be cancelled. + /// Therefore, the order process continues for validation. + /// + /// + /// + /// + public async Task Handle(GracePeriodConfirmedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId); + var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - command.GetGenericTypeName(), - nameof(command.OrderNumber), - command.OrderNumber, - command); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); - await _mediator.Send(command); - } + await _mediator.Send(command); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs index cad6123be..4170ac18f 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs @@ -1,46 +1,35 @@ -namespace Ordering.API.Application.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; + +public class OrderPaymentFailedIntegrationEventHandler : + IIntegrationEventHandler { - using MediatR; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.Commands; - using Ordering.API.Application.IntegrationEvents.Events; - using Serilog.Context; - using System; - using System.Threading.Tasks; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public class OrderPaymentFailedIntegrationEventHandler : - IIntegrationEventHandler + public OrderPaymentFailedIntegrationEventHandler( + IMediator mediator, + ILogger logger) { - private readonly IMediator _mediator; - private readonly ILogger _logger; - - public OrderPaymentFailedIntegrationEventHandler( - IMediator mediator, - ILogger logger) - { - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderPaymentFailedIntegrationEvent @event) + public async Task Handle(OrderPaymentFailedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var command = new CancelOrderCommand(@event.OrderId); + var command = new CancelOrderCommand(@event.OrderId); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - command.GetGenericTypeName(), - nameof(command.OrderNumber), - command.OrderNumber, - command); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); - await _mediator.Send(command); - } + await _mediator.Send(command); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSucceededIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSucceededIntegrationEventHandler.cs index 9971a1a33..4bd6304d0 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSucceededIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSucceededIntegrationEventHandler.cs @@ -1,46 +1,35 @@ -namespace Ordering.API.Application.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; + +public class OrderPaymentSucceededIntegrationEventHandler : + IIntegrationEventHandler { - using MediatR; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.Commands; - using Ordering.API.Application.IntegrationEvents.Events; - using Serilog.Context; - using System; - using System.Threading.Tasks; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public class OrderPaymentSucceededIntegrationEventHandler : - IIntegrationEventHandler + public OrderPaymentSucceededIntegrationEventHandler( + IMediator mediator, + ILogger logger) { - private readonly IMediator _mediator; - private readonly ILogger _logger; - - public OrderPaymentSucceededIntegrationEventHandler( - IMediator mediator, - ILogger logger) - { - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderPaymentSucceededIntegrationEvent @event) + public async Task Handle(OrderPaymentSucceededIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var command = new SetPaidOrderStatusCommand(@event.OrderId); + var command = new SetPaidOrderStatusCommand(@event.OrderId); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - command.GetGenericTypeName(), - nameof(command.OrderNumber), - command.OrderNumber, - command); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); - await _mediator.Send(command); - } + await _mediator.Send(command); } } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs index 8a349fca7..0c9557a5b 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs @@ -1,46 +1,35 @@ -namespace Ordering.API.Application.IntegrationEvents.EventHandling +namespace Ordering.API.Application.IntegrationEvents.EventHandling; + +public class OrderStockConfirmedIntegrationEventHandler : + IIntegrationEventHandler { - using Events; - using MediatR; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.Commands; - using Serilog.Context; - using System; - using System.Threading.Tasks; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public class OrderStockConfirmedIntegrationEventHandler : - IIntegrationEventHandler + public OrderStockConfirmedIntegrationEventHandler( + IMediator mediator, + ILogger logger) { - private readonly IMediator _mediator; - private readonly ILogger _logger; - - public OrderStockConfirmedIntegrationEventHandler( - IMediator mediator, - ILogger logger) - { - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStockConfirmedIntegrationEvent @event) + public async Task Handle(OrderStockConfirmedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId); + var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - command.GetGenericTypeName(), - nameof(command.OrderNumber), - command.OrderNumber, - command); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); - await _mediator.Send(command); - } + await _mediator.Send(command); } } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs index 5819b4fe3..4fa61b9b5 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs @@ -1,50 +1,38 @@ -namespace Ordering.API.Application.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; +public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler { - using Events; - using MediatR; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; - using Microsoft.Extensions.Logging; - using Ordering.API.Application.Commands; - using Serilog.Context; - using System.Linq; - using System.Threading.Tasks; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler + public OrderStockRejectedIntegrationEventHandler( + IMediator mediator, + ILogger logger) { - private readonly IMediator _mediator; - private readonly ILogger _logger; - - public OrderStockRejectedIntegrationEventHandler( - IMediator mediator, - ILogger logger) - { - _mediator = mediator; - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - } + _mediator = mediator; + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStockRejectedIntegrationEvent @event) + public async Task Handle(OrderStockRejectedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var orderStockRejectedItems = @event.OrderStockItems - .FindAll(c => !c.HasStock) - .Select(c => c.ProductId) - .ToList(); + var orderStockRejectedItems = @event.OrderStockItems + .FindAll(c => !c.HasStock) + .Select(c => c.ProductId) + .ToList(); - var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems); + var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - command.GetGenericTypeName(), - nameof(command.OrderNumber), - command.OrderNumber, - command); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); - await _mediator.Send(command); - } + await _mediator.Send(command); } } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs index c16b554c9..a5a15c06c 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs @@ -1,80 +1,69 @@ -using MediatR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.IntegrationEvents.Events; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; -namespace Ordering.API.Application.IntegrationEvents.EventHandling +public class UserCheckoutAcceptedIntegrationEventHandler : IIntegrationEventHandler { - public class UserCheckoutAcceptedIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IMediator _mediator; - private readonly ILogger _logger; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public UserCheckoutAcceptedIntegrationEventHandler( - IMediator mediator, - ILogger logger) - { - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public UserCheckoutAcceptedIntegrationEventHandler( + IMediator mediator, + ILogger logger) + { + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - /// - /// Integration event handler which starts the create order process - /// - /// - /// Integration event message which is sent by the - /// basket.api once it has successfully process the - /// order items. - /// - /// - public async Task Handle(UserCheckoutAcceptedIntegrationEvent @event) + /// + /// Integration event handler which starts the create order process + /// + /// + /// Integration event message which is sent by the + /// basket.api once it has successfully process the + /// order items. + /// + /// + public async Task Handle(UserCheckoutAcceptedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - var result = false; + var result = false; - if (@event.RequestId != Guid.Empty) + if (@event.RequestId != Guid.Empty) + { + using (LogContext.PushProperty("IdentifiedCommandId", @event.RequestId)) { - using (LogContext.PushProperty("IdentifiedCommandId", @event.RequestId)) - { - var createOrderCommand = new CreateOrderCommand(@event.Basket.Items, @event.UserId, @event.UserName, @event.City, @event.Street, - @event.State, @event.Country, @event.ZipCode, - @event.CardNumber, @event.CardHolderName, @event.CardExpiration, - @event.CardSecurityNumber, @event.CardTypeId); + var createOrderCommand = new CreateOrderCommand(@event.Basket.Items, @event.UserId, @event.UserName, @event.City, @event.Street, + @event.State, @event.Country, @event.ZipCode, + @event.CardNumber, @event.CardHolderName, @event.CardExpiration, + @event.CardSecurityNumber, @event.CardTypeId); - var requestCreateOrder = new IdentifiedCommand(createOrderCommand, @event.RequestId); + var requestCreateOrder = new IdentifiedCommand(createOrderCommand, @event.RequestId); - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - requestCreateOrder.GetGenericTypeName(), - nameof(requestCreateOrder.Id), - requestCreateOrder.Id, - requestCreateOrder); + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + requestCreateOrder.GetGenericTypeName(), + nameof(requestCreateOrder.Id), + requestCreateOrder.Id, + requestCreateOrder); - result = await _mediator.Send(requestCreateOrder); + result = await _mediator.Send(requestCreateOrder); - if (result) - { - _logger.LogInformation("----- CreateOrderCommand suceeded - RequestId: {RequestId}", @event.RequestId); - } - else - { - _logger.LogWarning("CreateOrderCommand failed - RequestId: {RequestId}", @event.RequestId); - } + if (result) + { + _logger.LogInformation("----- CreateOrderCommand suceeded - RequestId: {RequestId}", @event.RequestId); + } + else + { + _logger.LogWarning("CreateOrderCommand failed - RequestId: {RequestId}", @event.RequestId); } } - else - { - _logger.LogWarning("Invalid IntegrationEvent - RequestId is missing - {@IntegrationEvent}", @event); - } + } + else + { + _logger.LogWarning("Invalid IntegrationEvent - RequestId is missing - {@IntegrationEvent}", @event); } } } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/GracePeriodConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/GracePeriodConfirmedIntegrationEvent.cs index 1eac25205..3e653f8df 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/GracePeriodConfirmedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/GracePeriodConfirmedIntegrationEvent.cs @@ -1,12 +1,10 @@ -namespace Ordering.API.Application.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; - public record GracePeriodConfirmedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record GracePeriodConfirmedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public GracePeriodConfirmedIntegrationEvent(int orderId) => - OrderId = orderId; - } + public GracePeriodConfirmedIntegrationEvent(int orderId) => + OrderId = orderId; } + diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs index a4d1c70f6..42f247e4b 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs @@ -1,11 +1,8 @@ -namespace Ordering.API.Application.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; - public record OrderPaymentFailedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderPaymentFailedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId; - } -} \ No newline at end of file + public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs index 8897deb31..6dd575fe1 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs @@ -1,11 +1,8 @@ -namespace Ordering.API.Application.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; - public record OrderPaymentSucceededIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderPaymentSucceededIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public OrderPaymentSucceededIntegrationEvent(int orderId) => OrderId = orderId; - } -} \ No newline at end of file + public OrderPaymentSucceededIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs index 8f11e240f..0741b89e5 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs @@ -1,15 +1,12 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; -namespace Ordering.API.Application.IntegrationEvents.Events +// Integration Events notes: +// An Event is “something that has happened in the past”, therefore its name has to be +// An Integration Event is an event that can cause side effects to other microservices, Bounded-Contexts or external systems. +public record OrderStartedIntegrationEvent : IntegrationEvent { - // Integration Events notes: - // An Event is “something that has happened in the past”, therefore its name has to be - // An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems. - public record OrderStartedIntegrationEvent : IntegrationEvent - { - public string UserId { get; set; } + public string UserId { get; init; } - public OrderStartedIntegrationEvent(string userId) - => UserId = userId; - } -} \ No newline at end of file + public OrderStartedIntegrationEvent(string userId) + => UserId = userId; +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs index 72cd4b9f4..1f7ef35e2 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs @@ -1,34 +1,30 @@ -namespace Ordering.API.Application.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; + +public record OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using System.Collections.Generic; + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } + public IEnumerable OrderStockItems { get; } - public record OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent + public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, string orderStatus, string buyerName, + IEnumerable orderStockItems) { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } - public IEnumerable OrderStockItems { get; } - - public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, string orderStatus, string buyerName, - IEnumerable orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + OrderId = orderId; + OrderStockItems = orderStockItems; + OrderStatus = orderStatus; + BuyerName = buyerName; } +} - public record OrderStockItem - { - public int ProductId { get; } - public int Units { get; } +public record OrderStockItem +{ + public int ProductId { get; } + public int Units { get; } - public OrderStockItem(int productId, int units) - { - ProductId = productId; - Units = units; - } + public OrderStockItem(int productId, int units) + { + ProductId = productId; + Units = units; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs index b703e8031..170bc2d06 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs @@ -1,18 +1,15 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; -namespace Ordering.API.Application.IntegrationEvents.Events +public record OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToCancelledIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToCancelledIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs index ee5f07487..f40a4b625 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs @@ -1,24 +1,21 @@ -namespace Ordering.API.Application.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; + +public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using System.Collections.Generic; + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } + public IEnumerable OrderStockItems { get; } - public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent + public OrderStatusChangedToPaidIntegrationEvent(int orderId, + string orderStatus, + string buyerName, + IEnumerable orderStockItems) { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } - public IEnumerable OrderStockItems { get; } - - public OrderStatusChangedToPaidIntegrationEvent(int orderId, - string orderStatus, - string buyerName, - IEnumerable orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + OrderId = orderId; + OrderStockItems = orderStockItems; + OrderStatus = orderStatus; + BuyerName = buyerName; } } + diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs index 064d07c20..0ab7ae093 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs @@ -1,18 +1,15 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; -namespace Ordering.API.Application.IntegrationEvents.Events +public record OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs index d87e30b81..5450b570c 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs @@ -1,18 +1,15 @@ -namespace Ordering.API.Application.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; + +public record OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public record OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent + public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId, string orderStatus, string buyerName) { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } - - public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedTosubmittedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedTosubmittedIntegrationEvent.cs index 77b567ec8..e007d948e 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedTosubmittedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedTosubmittedIntegrationEvent.cs @@ -1,18 +1,15 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; -namespace Ordering.API.Application.IntegrationEvents.Events +public record OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs index 2b09c8655..93d541744 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs @@ -1,11 +1,8 @@ -namespace Ordering.API.Application.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; - public record OrderStockConfirmedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderStockConfirmedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public OrderStockConfirmedIntegrationEvent(int orderId) => OrderId = orderId; - } -} \ No newline at end of file + public OrderStockConfirmedIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs index c16148f84..25e1acf63 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockRejectedIntegrationEvent.cs @@ -1,31 +1,27 @@ -namespace Ordering.API.Application.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; - public record OrderStockRejectedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderStockRejectedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public List OrderStockItems { get; } + public List OrderStockItems { get; } - public OrderStockRejectedIntegrationEvent(int orderId, - List orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - } + public OrderStockRejectedIntegrationEvent(int orderId, + List orderStockItems) + { + OrderId = orderId; + OrderStockItems = orderStockItems; } +} - public record ConfirmedOrderStockItem - { - public int ProductId { get; } - public bool HasStock { get; } +public record ConfirmedOrderStockItem +{ + public int ProductId { get; } + public bool HasStock { get; } - public ConfirmedOrderStockItem(int productId, bool hasStock) - { - ProductId = productId; - HasStock = hasStock; - } + public ConfirmedOrderStockItem(int productId, bool hasStock) + { + ProductId = productId; + HasStock = hasStock; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs index 4cd74b16b..811be0ec4 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/UserCheckoutAcceptedIntegrationEvent.cs @@ -1,62 +1,57 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Ordering.API.Application.Models; -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; -namespace Ordering.API.Application.IntegrationEvents.Events -{ - public record UserCheckoutAcceptedIntegrationEvent : IntegrationEvent - { - public string UserId { get; } - - public string UserName { get; } - - public string City { get; set; } - - public string Street { get; set; } +public record UserCheckoutAcceptedIntegrationEvent : IntegrationEvent +{ + public string UserId { get; } + + public string UserName { get; } + + public string City { get; set; } + + public string Street { get; set; } + + public string State { get; set; } - public string State { get; set; } + public string Country { get; set; } - public string Country { get; set; } + public string ZipCode { get; set; } - public string ZipCode { get; set; } + public string CardNumber { get; set; } - public string CardNumber { get; set; } + public string CardHolderName { get; set; } - public string CardHolderName { get; set; } + public DateTime CardExpiration { get; set; } - public DateTime CardExpiration { get; set; } + public string CardSecurityNumber { get; set; } - public string CardSecurityNumber { get; set; } + public int CardTypeId { get; set; } - public int CardTypeId { get; set; } + public string Buyer { get; set; } - public string Buyer { get; set; } + public Guid RequestId { get; set; } - public Guid RequestId { get; set; } - - public CustomerBasket Basket { get; } - - public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street, - string state, string country, string zipCode, string cardNumber, string cardHolderName, - DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, - CustomerBasket basket) - { - UserId = userId; - City = city; - Street = street; - State = state; - Country = country; - ZipCode = zipCode; - CardNumber = cardNumber; - CardHolderName = cardHolderName; - CardExpiration = cardExpiration; - CardSecurityNumber = cardSecurityNumber; - CardTypeId = cardTypeId; - Buyer = buyer; - Basket = basket; - RequestId = requestId; - UserName = userName; - } + public CustomerBasket Basket { get; } + public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street, + string state, string country, string zipCode, string cardNumber, string cardHolderName, + DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId, + CustomerBasket basket) + { + UserId = userId; + City = city; + Street = street; + State = state; + Country = country; + ZipCode = zipCode; + CardNumber = cardNumber; + CardHolderName = cardHolderName; + CardExpiration = cardExpiration; + CardSecurityNumber = cardSecurityNumber; + CardTypeId = cardTypeId; + Buyer = buyer; + Basket = basket; + RequestId = requestId; + UserName = userName; } + } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs index ad661e3c0..18807a56b 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs @@ -1,12 +1,7 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents; -namespace Ordering.API.Application.IntegrationEvents +public interface IOrderingIntegrationEventService { - public interface IOrderingIntegrationEventService - { - Task PublishEventsThroughEventBusAsync(Guid transactionId); - Task AddAndSaveEventAsync(IntegrationEvent evt); - } + Task PublishEventsThroughEventBusAsync(Guid transactionId); + Task AddAndSaveEventAsync(IntegrationEvent evt); } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs index a559a8ffa..e2545cae5 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs @@ -1,65 +1,53 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Microsoft.Extensions.Logging; -using System; -using System.Data.Common; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents; -namespace Ordering.API.Application.IntegrationEvents +public class OrderingIntegrationEventService : IOrderingIntegrationEventService { - public class OrderingIntegrationEventService : IOrderingIntegrationEventService + private readonly Func _integrationEventLogServiceFactory; + private readonly IEventBus _eventBus; + private readonly OrderingContext _orderingContext; + private readonly IIntegrationEventLogService _eventLogService; + private readonly ILogger _logger; + + public OrderingIntegrationEventService(IEventBus eventBus, + OrderingContext orderingContext, + IntegrationEventLogContext eventLogContext, + Func integrationEventLogServiceFactory, + ILogger logger) { - private readonly Func _integrationEventLogServiceFactory; - private readonly IEventBus _eventBus; - private readonly OrderingContext _orderingContext; - private readonly IIntegrationEventLogService _eventLogService; - private readonly ILogger _logger; + _orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext)); + _integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory)); + _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); + _eventLogService = _integrationEventLogServiceFactory(_orderingContext.Database.GetDbConnection()); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public OrderingIntegrationEventService(IEventBus eventBus, - OrderingContext orderingContext, - IntegrationEventLogContext eventLogContext, - Func integrationEventLogServiceFactory, - ILogger logger) - { - _orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext)); - _integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory)); - _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); - _eventLogService = _integrationEventLogServiceFactory(_orderingContext.Database.GetDbConnection()); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public async Task PublishEventsThroughEventBusAsync(Guid transactionId) + { + var pendingLogEvents = await _eventLogService.RetrieveEventLogsPendingToPublishAsync(transactionId); - public async Task PublishEventsThroughEventBusAsync(Guid transactionId) + foreach (var logEvt in pendingLogEvents) { - var pendingLogEvents = await _eventLogService.RetrieveEventLogsPendingToPublishAsync(transactionId); + _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", logEvt.EventId, Program.AppName, logEvt.IntegrationEvent); - foreach (var logEvt in pendingLogEvents) + try { - _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", logEvt.EventId, Program.AppName, logEvt.IntegrationEvent); - - try - { - await _eventLogService.MarkEventAsInProgressAsync(logEvt.EventId); - _eventBus.Publish(logEvt.IntegrationEvent); - await _eventLogService.MarkEventAsPublishedAsync(logEvt.EventId); - } - catch (Exception ex) - { - _logger.LogError(ex, "ERROR publishing integration event: {IntegrationEventId} from {AppName}", logEvt.EventId, Program.AppName); + await _eventLogService.MarkEventAsInProgressAsync(logEvt.EventId); + _eventBus.Publish(logEvt.IntegrationEvent); + await _eventLogService.MarkEventAsPublishedAsync(logEvt.EventId); + } + catch (Exception ex) + { + _logger.LogError(ex, "ERROR publishing integration event: {IntegrationEventId} from {AppName}", logEvt.EventId, Program.AppName); - await _eventLogService.MarkEventAsFailedAsync(logEvt.EventId); - } + await _eventLogService.MarkEventAsFailedAsync(logEvt.EventId); } } + } - public async Task AddAndSaveEventAsync(IntegrationEvent evt) - { - _logger.LogInformation("----- Enqueuing integration event {IntegrationEventId} to repository ({@IntegrationEvent})", evt.Id, evt); + public async Task AddAndSaveEventAsync(IntegrationEvent evt) + { + _logger.LogInformation("----- Enqueuing integration event {IntegrationEventId} to repository ({@IntegrationEvent})", evt.Id, evt); - await _eventLogService.SaveEventAsync(evt, _orderingContext.GetCurrentTransaction()); - } + await _eventLogService.SaveEventAsync(evt, _orderingContext.GetCurrentTransaction()); } } diff --git a/src/Services/Ordering/Ordering.API/Application/Models/BasketItem.cs b/src/Services/Ordering/Ordering.API/Application/Models/BasketItem.cs index 5c7df3338..ca07701c0 100644 --- a/src/Services/Ordering/Ordering.API/Application/Models/BasketItem.cs +++ b/src/Services/Ordering/Ordering.API/Application/Models/BasketItem.cs @@ -1,13 +1,13 @@ -namespace Ordering.API.Application.Models +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; + +public class BasketItem { - public class BasketItem - { - public string Id { get; init; } - public int ProductId { get; init; } - public string ProductName { get; init; } - public decimal UnitPrice { get; init; } - public decimal OldUnitPrice { get; init; } - public int Quantity { get; init; } - public string PictureUrl { get; init; } - } + public string Id { get; init; } + public int ProductId { get; init; } + public string ProductName { get; init; } + public decimal UnitPrice { get; init; } + public decimal OldUnitPrice { get; init; } + public int Quantity { get; init; } + public string PictureUrl { get; init; } } + diff --git a/src/Services/Ordering/Ordering.API/Application/Models/CustomerBasket.cs b/src/Services/Ordering/Ordering.API/Application/Models/CustomerBasket.cs index e455f5d7d..919c0ba21 100644 --- a/src/Services/Ordering/Ordering.API/Application/Models/CustomerBasket.cs +++ b/src/Services/Ordering/Ordering.API/Application/Models/CustomerBasket.cs @@ -1,16 +1,13 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; -namespace Ordering.API.Application.Models +public class CustomerBasket { - public class CustomerBasket - { - public string BuyerId { get; set; } - public List Items { get; set; } + public string BuyerId { get; set; } + public List Items { get; set; } - public CustomerBasket(string customerId) - { - BuyerId = customerId; - Items = new List(); - } + public CustomerBasket(string buyerId, List items) + { + BuyerId = buyerId; + Items = items; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs index 89cf496e3..60c6fe286 100644 --- a/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs +++ b/src/Services/Ordering/Ordering.API/Application/Queries/IOrderQueries.cs @@ -1,15 +1,10 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries -{ - using System; - using System.Collections.Generic; - using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; - public interface IOrderQueries - { - Task GetOrderAsync(int id); +public interface IOrderQueries +{ + Task GetOrderAsync(int id); - Task> GetOrdersFromUserAsync(Guid userId); + Task> GetOrdersFromUserAsync(Guid userId); - Task> GetCardTypesAsync(); - } + Task> GetCardTypesAsync(); } diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs index ceffa9039..860c587c4 100644 --- a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs +++ b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs @@ -1,105 +1,92 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; + +public class OrderQueries + : IOrderQueries { - using Dapper; - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - using System.Threading.Tasks; + private string _connectionString = string.Empty; - public class OrderQueries - : IOrderQueries + public OrderQueries(string constr) { - private string _connectionString = string.Empty; + _connectionString = !string.IsNullOrWhiteSpace(constr) ? constr : throw new ArgumentNullException(nameof(constr)); + } - public OrderQueries(string constr) - { - _connectionString = !string.IsNullOrWhiteSpace(constr) ? constr : throw new ArgumentNullException(nameof(constr)); - } + public async Task GetOrderAsync(int id) + { + using var connection = new SqlConnection(_connectionString); + connection.Open(); - public async Task GetOrderAsync(int id) - { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + var result = await connection.QueryAsync( + @"select o.[Id] as ordernumber,o.OrderDate as date, o.Description as description, + o.Address_City as city, o.Address_Country as country, o.Address_State as state, o.Address_Street as street, o.Address_ZipCode as zipcode, + os.Name as status, + oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl + FROM ordering.Orders o + LEFT JOIN ordering.Orderitems oi ON o.Id = oi.orderid + LEFT JOIN ordering.orderstatus os on o.OrderStatusId = os.Id + WHERE o.Id=@id" + , new { id } + ); - var result = await connection.QueryAsync( - @"select o.[Id] as ordernumber,o.OrderDate as date, o.Description as description, - o.Address_City as city, o.Address_Country as country, o.Address_State as state, o.Address_Street as street, o.Address_ZipCode as zipcode, - os.Name as status, - oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl - FROM ordering.Orders o - LEFT JOIN ordering.Orderitems oi ON o.Id = oi.orderid - LEFT JOIN ordering.orderstatus os on o.OrderStatusId = os.Id - WHERE o.Id=@id" - , new { id } - ); + if (result.AsList().Count == 0) + throw new KeyNotFoundException(); - if (result.AsList().Count == 0) - throw new KeyNotFoundException(); + return MapOrderItems(result); + } - return MapOrderItems(result); - } - } + public async Task> GetOrdersFromUserAsync(Guid userId) + { + using var connection = new SqlConnection(_connectionString); + connection.Open(); - public async Task> GetOrdersFromUserAsync(Guid userId) - { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total + FROM [ordering].[Orders] o + LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid + LEFT JOIN[ordering].[orderstatus] os on o.OrderStatusId = os.Id + LEFT JOIN[ordering].[buyers] ob on o.BuyerId = ob.Id + WHERE ob.IdentityGuid = @userId + GROUP BY o.[Id], o.[OrderDate], os.[Name] + ORDER BY o.[Id]", new { userId }); + } - return await connection.QueryAsync(@"SELECT o.[Id] as ordernumber,o.[OrderDate] as [date],os.[Name] as [status], SUM(oi.units*oi.unitprice) as total - FROM [ordering].[Orders] o - LEFT JOIN[ordering].[orderitems] oi ON o.Id = oi.orderid - LEFT JOIN[ordering].[orderstatus] os on o.OrderStatusId = os.Id - LEFT JOIN[ordering].[buyers] ob on o.BuyerId = ob.Id - WHERE ob.IdentityGuid = @userId - GROUP BY o.[Id], o.[OrderDate], os.[Name] - ORDER BY o.[Id]", new { userId }); - } - } + public async Task> GetCardTypesAsync() + { + using var connection = new SqlConnection(_connectionString); + connection.Open(); - public async Task> GetCardTypesAsync() - { - using (var connection = new SqlConnection(_connectionString)) - { - connection.Open(); + return await connection.QueryAsync("SELECT * FROM ordering.cardtypes"); + } - return await connection.QueryAsync("SELECT * FROM ordering.cardtypes"); - } - } + private Order MapOrderItems(dynamic result) + { + var order = new Order + { + ordernumber = result[0].ordernumber, + date = result[0].date, + status = result[0].status, + description = result[0].description, + street = result[0].street, + city = result[0].city, + zipcode = result[0].zipcode, + country = result[0].country, + orderitems = new List(), + total = 0 + }; - private Order MapOrderItems(dynamic result) + foreach (dynamic item in result) { - var order = new Order + var orderitem = new Orderitem { - ordernumber = result[0].ordernumber, - date = result[0].date, - status = result[0].status, - description = result[0].description, - street = result[0].street, - city = result[0].city, - zipcode = result[0].zipcode, - country = result[0].country, - orderitems = new List(), - total = 0 + productname = item.productname, + units = item.units, + unitprice = (double)item.unitprice, + pictureurl = item.pictureurl }; - foreach (dynamic item in result) - { - var orderitem = new Orderitem - { - productname = item.productname, - units = item.units, - unitprice = (double)item.unitprice, - pictureurl = item.pictureurl - }; - - order.total += item.units * item.unitprice; - order.orderitems.Add(orderitem); - } - - return order; + order.total += item.units * item.unitprice; + order.orderitems.Add(orderitem); } + + return order; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/OrderViewModel.cs b/src/Services/Ordering/Ordering.API/Application/Queries/OrderViewModel.cs index 84f9f3f40..d5ce86005 100644 --- a/src/Services/Ordering/Ordering.API/Application/Queries/OrderViewModel.cs +++ b/src/Services/Ordering/Ordering.API/Application/Queries/OrderViewModel.cs @@ -1,41 +1,37 @@ -using System; -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries +public record Orderitem { - public record Orderitem - { - public string productname { get; init; } - public int units { get; init; } - public double unitprice { get; init; } - public string pictureurl { get; init; } - } + public string productname { get; init; } + public int units { get; init; } + public double unitprice { get; init; } + public string pictureurl { get; init; } +} - public record Order - { - public int ordernumber { get; init; } - public DateTime date { get; init; } - public string status { get; init; } - public string description { get; init; } - public string street { get; init; } - public string city { get; init; } - public string zipcode { get; init; } - public string country { get; init; } - public List orderitems { get; set; } - public decimal total { get; set; } - } +public record Order +{ + public int ordernumber { get; init; } + public DateTime date { get; init; } + public string status { get; init; } + public string description { get; init; } + public string street { get; init; } + public string city { get; init; } + public string zipcode { get; init; } + public string country { get; init; } + public List orderitems { get; set; } + public decimal total { get; set; } +} - public record OrderSummary - { - public int ordernumber { get; init; } - public DateTime date { get; init; } - public string status { get; init; } - public double total { get; init; } - } +public record OrderSummary +{ + public int ordernumber { get; init; } + public DateTime date { get; init; } + public string status { get; init; } + public double total { get; init; } +} - public record CardType - { - public int Id { get; init; } - public string Name { get; init; } - } +public record CardType +{ + public int Id { get; init; } + public string Name { get; init; } } diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs index 49b4c9413..7d901b1fe 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/CancelOrderCommandValidator.cs @@ -1,16 +1,11 @@ -using FluentValidation; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.Commands; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Validations; -namespace Ordering.API.Application.Validations +public class CancelOrderCommandValidator : AbstractValidator { - public class CancelOrderCommandValidator : AbstractValidator + public CancelOrderCommandValidator(ILogger logger) { - public CancelOrderCommandValidator(ILogger logger) - { - RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); + RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); - logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); - } + logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs index d3b09233a..eb61082e7 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/CreateOrderCommandValidator.cs @@ -1,40 +1,33 @@ -using FluentValidation; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Validations; + using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; -namespace Ordering.API.Application.Validations +public class CreateOrderCommandValidator : AbstractValidator { - public class CreateOrderCommandValidator : AbstractValidator + public CreateOrderCommandValidator(ILogger logger) { - public CreateOrderCommandValidator(ILogger logger) - { - RuleFor(command => command.City).NotEmpty(); - RuleFor(command => command.Street).NotEmpty(); - RuleFor(command => command.State).NotEmpty(); - RuleFor(command => command.Country).NotEmpty(); - RuleFor(command => command.ZipCode).NotEmpty(); - RuleFor(command => command.CardNumber).NotEmpty().Length(12, 19); - RuleFor(command => command.CardHolderName).NotEmpty(); - RuleFor(command => command.CardExpiration).NotEmpty().Must(BeValidExpirationDate).WithMessage("Please specify a valid card expiration date"); - RuleFor(command => command.CardSecurityNumber).NotEmpty().Length(3); - RuleFor(command => command.CardTypeId).NotEmpty(); - RuleFor(command => command.OrderItems).Must(ContainOrderItems).WithMessage("No order items found"); + RuleFor(command => command.City).NotEmpty(); + RuleFor(command => command.Street).NotEmpty(); + RuleFor(command => command.State).NotEmpty(); + RuleFor(command => command.Country).NotEmpty(); + RuleFor(command => command.ZipCode).NotEmpty(); + RuleFor(command => command.CardNumber).NotEmpty().Length(12, 19); + RuleFor(command => command.CardHolderName).NotEmpty(); + RuleFor(command => command.CardExpiration).NotEmpty().Must(BeValidExpirationDate).WithMessage("Please specify a valid card expiration date"); + RuleFor(command => command.CardSecurityNumber).NotEmpty().Length(3); + RuleFor(command => command.CardTypeId).NotEmpty(); + RuleFor(command => command.OrderItems).Must(ContainOrderItems).WithMessage("No order items found"); - logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); - } + logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); + } - private bool BeValidExpirationDate(DateTime dateTime) - { - return dateTime >= DateTime.UtcNow; - } + private bool BeValidExpirationDate(DateTime dateTime) + { + return dateTime >= DateTime.UtcNow; + } - private bool ContainOrderItems(IEnumerable orderItems) - { - return orderItems.Any(); - } + private bool ContainOrderItems(IEnumerable orderItems) + { + return orderItems.Any(); } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs index ea928475d..bde2d771f 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/IdentifiedCommandValidator.cs @@ -1,16 +1,11 @@ -using FluentValidation; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.Extensions.Logging; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Validations; -namespace Ordering.API.Application.Validations +public class IdentifiedCommandValidator : AbstractValidator> { - public class IdentifiedCommandValidator : AbstractValidator> + public IdentifiedCommandValidator(ILogger logger) { - public IdentifiedCommandValidator(ILogger logger) - { - RuleFor(command => command.Id).NotEmpty(); + RuleFor(command => command.Id).NotEmpty(); - logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); - } + logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); } } diff --git a/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs b/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs index fbc294534..0341c6028 100644 --- a/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs +++ b/src/Services/Ordering/Ordering.API/Application/Validations/ShipOrderCommandValidator.cs @@ -1,16 +1,11 @@ -using FluentValidation; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.Commands; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Validations; -namespace Ordering.API.Application.Validations +public class ShipOrderCommandValidator : AbstractValidator { - public class ShipOrderCommandValidator : AbstractValidator + public ShipOrderCommandValidator(ILogger logger) { - public ShipOrderCommandValidator(ILogger logger) - { - RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); + RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); - logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); - } + logger.LogTrace("----- INSTANCE CREATED - {ClassName}", GetType().Name); } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Controllers/HomeController.cs b/src/Services/Ordering/Ordering.API/Controllers/HomeController.cs index ba4620b23..601b7ab6d 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/HomeController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/HomeController.cs @@ -1,13 +1,10 @@ -using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers +public class HomeController : Controller { - public class HomeController : Controller + // GET: // + public IActionResult Index() { - // GET: // - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } + return new RedirectResult("~/swagger"); } } diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index e31568d98..2cfd4063f 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -1,153 +1,143 @@ -using MediatR; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; -using Microsoft.Extensions.Logging; -using Ordering.API.Application.Commands; -using System; -using System.Collections.Generic; -using System.Net; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers + +[Route("api/v1/[controller]")] +[Authorize] +[ApiController] +public class OrdersController : ControllerBase { - [Route("api/v1/[controller]")] - [Authorize] - [ApiController] - public class OrdersController : ControllerBase + private readonly IMediator _mediator; + private readonly IOrderQueries _orderQueries; + private readonly IIdentityService _identityService; + private readonly ILogger _logger; + + public OrdersController( + IMediator mediator, + IOrderQueries orderQueries, + IIdentityService identityService, + ILogger logger) { - private readonly IMediator _mediator; - private readonly IOrderQueries _orderQueries; - private readonly IIdentityService _identityService; - private readonly ILogger _logger; - - public OrdersController( - IMediator mediator, - IOrderQueries orderQueries, - IIdentityService identityService, - ILogger logger) - { - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - _orderQueries = orderQueries ?? throw new ArgumentNullException(nameof(orderQueries)); - _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } - - [Route("cancel")] - [HttpPut] - [ProducesResponseType((int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - public async Task CancelOrderAsync([FromBody] CancelOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId) - { - bool commandResult = false; - - if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) - { - var requestCancelOrder = new IdentifiedCommand(command, guid); + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _orderQueries = orderQueries ?? throw new ArgumentNullException(nameof(orderQueries)); + _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - requestCancelOrder.GetGenericTypeName(), - nameof(requestCancelOrder.Command.OrderNumber), - requestCancelOrder.Command.OrderNumber, - requestCancelOrder); + [Route("cancel")] + [HttpPut] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + public async Task CancelOrderAsync([FromBody] CancelOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId) + { + bool commandResult = false; - commandResult = await _mediator.Send(requestCancelOrder); - } + if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) + { + var requestCancelOrder = new IdentifiedCommand(command, guid); - if (!commandResult) - { - return BadRequest(); - } + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + requestCancelOrder.GetGenericTypeName(), + nameof(requestCancelOrder.Command.OrderNumber), + requestCancelOrder.Command.OrderNumber, + requestCancelOrder); - return Ok(); + commandResult = await _mediator.Send(requestCancelOrder); } - [Route("ship")] - [HttpPut] - [ProducesResponseType((int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - public async Task ShipOrderAsync([FromBody] ShipOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId) + if (!commandResult) { - bool commandResult = false; + return BadRequest(); + } - if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) - { - var requestShipOrder = new IdentifiedCommand(command, guid); + return Ok(); + } - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - requestShipOrder.GetGenericTypeName(), - nameof(requestShipOrder.Command.OrderNumber), - requestShipOrder.Command.OrderNumber, - requestShipOrder); + [Route("ship")] + [HttpPut] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + public async Task ShipOrderAsync([FromBody] ShipOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId) + { + bool commandResult = false; - commandResult = await _mediator.Send(requestShipOrder); - } + if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) + { + var requestShipOrder = new IdentifiedCommand(command, guid); - if (!commandResult) - { - return BadRequest(); - } + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + requestShipOrder.GetGenericTypeName(), + nameof(requestShipOrder.Command.OrderNumber), + requestShipOrder.Command.OrderNumber, + requestShipOrder); - return Ok(); + commandResult = await _mediator.Send(requestShipOrder); } - [Route("{orderId:int}")] - [HttpGet] - [ProducesResponseType(typeof(Order), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task GetOrderAsync(int orderId) + if (!commandResult) { - try - { - //Todo: It's good idea to take advantage of GetOrderByIdQuery and handle by GetCustomerByIdQueryHandler - //var order customer = await _mediator.Send(new GetOrderByIdQuery(orderId)); - var order = await _orderQueries.GetOrderAsync(orderId); - - return Ok(order); - } - catch - { - return NotFound(); - } + return BadRequest(); } - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task>> GetOrdersAsync() + return Ok(); + } + + [Route("{orderId:int}")] + [HttpGet] + [ProducesResponseType(typeof(Order), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task GetOrderAsync(int orderId) + { + try { - var userid = _identityService.GetUserIdentity(); - var orders = await _orderQueries.GetOrdersFromUserAsync(Guid.Parse(userid)); + //Todo: It's good idea to take advantage of GetOrderByIdQuery and handle by GetCustomerByIdQueryHandler + //var order customer = await _mediator.Send(new GetOrderByIdQuery(orderId)); + var order = await _orderQueries.GetOrderAsync(orderId); - return Ok(orders); + return Ok(order); } - - [Route("cardtypes")] - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task>> GetCardTypesAsync() + catch { - var cardTypes = await _orderQueries.GetCardTypesAsync(); - - return Ok(cardTypes); + return NotFound(); } + } - [Route("draft")] - [HttpPost] - public async Task> CreateOrderDraftFromBasketDataAsync([FromBody] CreateOrderDraftCommand createOrderDraftCommand) - { - _logger.LogInformation( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - createOrderDraftCommand.GetGenericTypeName(), - nameof(createOrderDraftCommand.BuyerId), - createOrderDraftCommand.BuyerId, - createOrderDraftCommand); + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task>> GetOrdersAsync() + { + var userid = _identityService.GetUserIdentity(); + var orders = await _orderQueries.GetOrdersFromUserAsync(Guid.Parse(userid)); - return await _mediator.Send(createOrderDraftCommand); - } + return Ok(orders); + } + + [Route("cardtypes")] + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task>> GetCardTypesAsync() + { + var cardTypes = await _orderQueries.GetCardTypesAsync(); + + return Ok(cardTypes); + } + + [Route("draft")] + [HttpPost] + public async Task> CreateOrderDraftFromBasketDataAsync([FromBody] CreateOrderDraftCommand createOrderDraftCommand) + { + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + createOrderDraftCommand.GetGenericTypeName(), + nameof(createOrderDraftCommand.BuyerId), + createOrderDraftCommand.BuyerId, + createOrderDraftCommand); + + return await _mediator.Send(createOrderDraftCommand); } } diff --git a/src/Services/Ordering/Ordering.API/Dockerfile b/src/Services/Ordering/Ordering.API/Dockerfile index 7659da4de..905d3bcd0 100644 --- a/src/Services/Ordering/Ordering.API/Dockerfile +++ b/src/Services/Ordering/Ordering.API/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Ordering/Ordering.API/Dockerfile.develop b/src/Services/Ordering/Ordering.API/Dockerfile.develop index 5f7200c84..c12e34af9 100644 --- a/src/Services/Ordering/Ordering.API/Dockerfile.develop +++ b/src/Services/Ordering/Ordering.API/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs b/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs index bbbc679ba..0f6122a13 100644 --- a/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs +++ b/src/Services/Ordering/Ordering.API/Extensions/BasketItemExtensions.cs @@ -1,28 +1,27 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; + +using System.Collections.Generic; using static Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands.CreateOrderCommand; -namespace Ordering.API.Application.Models +public static class BasketItemExtensions { - public static class BasketItemExtensions + public static IEnumerable ToOrderItemsDTO(this IEnumerable basketItems) { - public static IEnumerable ToOrderItemsDTO(this IEnumerable basketItems) + foreach (var item in basketItems) { - foreach (var item in basketItems) - { - yield return item.ToOrderItemDTO(); - } + yield return item.ToOrderItemDTO(); } + } - public static OrderItemDTO ToOrderItemDTO(this BasketItem item) + public static OrderItemDTO ToOrderItemDTO(this BasketItem item) + { + return new OrderItemDTO() { - return new OrderItemDTO() - { - ProductId = item.ProductId, - ProductName = item.ProductName, - PictureUrl = item.PictureUrl, - UnitPrice = item.UnitPrice, - Units = item.Quantity - }; - } + ProductId = item.ProductId, + ProductName = item.ProductName, + PictureUrl = item.PictureUrl, + UnitPrice = item.UnitPrice, + Units = item.Quantity + }; } } diff --git a/src/Services/Ordering/Ordering.API/Extensions/LinqSelectExtensions.cs b/src/Services/Ordering/Ordering.API/Extensions/LinqSelectExtensions.cs index 4efe08c07..c36385d6c 100644 --- a/src/Services/Ordering/Ordering.API/Extensions/LinqSelectExtensions.cs +++ b/src/Services/Ordering/Ordering.API/Extensions/LinqSelectExtensions.cs @@ -1,50 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Extensions; -namespace Ordering.API.Extensions +public static class LinqSelectExtensions { - public static class LinqSelectExtensions + public static IEnumerable> SelectTry(this IEnumerable enumerable, Func selector) { - public static IEnumerable> SelectTry(this IEnumerable enumerable, Func selector) + foreach (TSource element in enumerable) { - foreach (TSource element in enumerable) + SelectTryResult returnedValue; + try { - SelectTryResult returnedValue; - try - { - returnedValue = new SelectTryResult(element, selector(element), null); - } - catch (Exception ex) - { - returnedValue = new SelectTryResult(element, default(TResult), ex); - } - yield return returnedValue; + returnedValue = new SelectTryResult(element, selector(element), null); } + catch (Exception ex) + { + returnedValue = new SelectTryResult(element, default(TResult), ex); + } + yield return returnedValue; } + } - public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) - { - return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException)); - } + public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) + { + return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException)); + } - public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) - { - return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException)); - } + public static IEnumerable OnCaughtException(this IEnumerable> enumerable, Func exceptionHandler) + { + return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException)); + } - public class SelectTryResult + public class SelectTryResult + { + internal SelectTryResult(TSource source, TResult result, Exception exception) { - internal SelectTryResult(TSource source, TResult result, Exception exception) - { - Source = source; - Result = result; - CaughtException = exception; - } - - public TSource Source { get; private set; } - public TResult Result { get; private set; } - public Exception CaughtException { get; private set; } + Source = source; + Result = result; + CaughtException = exception; } + + public TSource Source { get; private set; } + public TResult Result { get; private set; } + public Exception CaughtException { get; private set; } } } diff --git a/src/Services/Ordering/Ordering.API/GlobalUsings.cs b/src/Services/Ordering/Ordering.API/GlobalUsings.cs new file mode 100644 index 000000000..a9ac5683a --- /dev/null +++ b/src/Services/Ordering/Ordering.API/GlobalUsings.cs @@ -0,0 +1,86 @@ +global using ApiModels = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; +global using AppCommand = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using Azure.Core; +global using Azure.Identity; +global using Dapper; +global using FluentValidation; +global using Google.Protobuf.Collections; +global using Grpc.Core; +global using HealthChecks.UI.Client; +global using MediatR; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc.Authorization; +global using Microsoft.AspNetCore.Mvc.Filters; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore.Server.Kestrel.Core; +global using Microsoft.AspNetCore; +global using Azure.Messaging.ServiceBus; +global using Microsoft.EntityFrameworkCore.Design; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Behaviors; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderStartedEvent; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderStockConfirmed; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Validations; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Extensions; +global using GrpcOrdering; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Filters; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; +global using Microsoft.eShopOnContainers.Services.Ordering.API; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Exceptions; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Microsoft.OpenApi.Models; +global using Polly.Retry; +global using Polly; +global using RabbitMQ.Client; +global using Serilog.Context; +global using Serilog; +global using Swashbuckle.AspNetCore.SwaggerGen; +global using System.Collections.Generic; +global using System.Data.Common; +global using System.Data.SqlClient; +global using System.IdentityModel.Tokens.Jwt; +global using System.IO; +global using System.Linq; +global using System.Net; +global using System.Reflection; +global using System.Runtime.Serialization; +global using System.Threading.Tasks; +global using System.Threading; +global using System; +global using System.Collections.Generic; diff --git a/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs b/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs index 3ae6c1733..969a09d46 100644 --- a/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs +++ b/src/Services/Ordering/Ordering.API/Grpc/OrderingService.cs @@ -1,90 +1,78 @@ -using Google.Protobuf.Collections; -using Grpc.Core; -using MediatR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; -using Microsoft.Extensions.Logging; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using ApiModels = Ordering.API.Application.Models; -using AppCommand = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +namespace GrpcOrdering; -namespace GrpcOrdering +public class OrderingService : OrderingGrpc.OrderingGrpcBase { - public class OrderingService : OrderingGrpc.OrderingGrpcBase - { - private readonly IMediator _mediator; - private readonly ILogger _logger; + private readonly IMediator _mediator; + private readonly ILogger _logger; - public OrderingService(IMediator mediator, ILogger logger) - { - _mediator = mediator; - _logger = logger; - } - - public override async Task CreateOrderDraftFromBasketData(CreateOrderDraftCommand createOrderDraftCommand, ServerCallContext context) - { - _logger.LogInformation("Begin grpc call from method {Method} for ordering get order draft {CreateOrderDraftCommand}", context.Method, createOrderDraftCommand); - _logger.LogTrace( - "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", - createOrderDraftCommand.GetGenericTypeName(), - nameof(createOrderDraftCommand.BuyerId), - createOrderDraftCommand.BuyerId, - createOrderDraftCommand); + public OrderingService(IMediator mediator, ILogger logger) + { + _mediator = mediator; + _logger = logger; + } - var command = new AppCommand.CreateOrderDraftCommand( - createOrderDraftCommand.BuyerId, - this.MapBasketItems(createOrderDraftCommand.Items)); + public override async Task CreateOrderDraftFromBasketData(CreateOrderDraftCommand createOrderDraftCommand, ServerCallContext context) + { + _logger.LogInformation("Begin grpc call from method {Method} for ordering get order draft {CreateOrderDraftCommand}", context.Method, createOrderDraftCommand); + _logger.LogTrace( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + createOrderDraftCommand.GetGenericTypeName(), + nameof(createOrderDraftCommand.BuyerId), + createOrderDraftCommand.BuyerId, + createOrderDraftCommand); + var command = new AppCommand.CreateOrderDraftCommand( + createOrderDraftCommand.BuyerId, + this.MapBasketItems(createOrderDraftCommand.Items)); - var data = await _mediator.Send(command); - if (data != null) - { - context.Status = new Status(StatusCode.OK, $" ordering get order draft {createOrderDraftCommand} do exist"); + var data = await _mediator.Send(command); - return this.MapResponse(data); - } - else - { - context.Status = new Status(StatusCode.NotFound, $" ordering get order draft {createOrderDraftCommand} do not exist"); - } + if (data != null) + { + context.Status = new Status(StatusCode.OK, $" ordering get order draft {createOrderDraftCommand} do exist"); - return new OrderDraftDTO(); + return this.MapResponse(data); } + else + { + context.Status = new Status(StatusCode.NotFound, $" ordering get order draft {createOrderDraftCommand} do not exist"); + } + + return new OrderDraftDTO(); + } - public OrderDraftDTO MapResponse(AppCommand.OrderDraftDTO order) + public OrderDraftDTO MapResponse(AppCommand.OrderDraftDTO order) + { + var result = new OrderDraftDTO() { - var result = new OrderDraftDTO() - { - Total = (double)order.Total, - }; + Total = (double)order.Total, + }; - order.OrderItems.ToList().ForEach(i => result.OrderItems.Add(new OrderItemDTO() - { - Discount = (double)i.Discount, - PictureUrl = i.PictureUrl, - ProductId = i.ProductId, - ProductName = i.ProductName, - UnitPrice = (double)i.UnitPrice, - Units = i.Units, - })); + order.OrderItems.ToList().ForEach(i => result.OrderItems.Add(new OrderItemDTO() + { + Discount = (double)i.Discount, + PictureUrl = i.PictureUrl, + ProductId = i.ProductId, + ProductName = i.ProductName, + UnitPrice = (double)i.UnitPrice, + Units = i.Units, + })); - return result; - } + return result; + } - public IEnumerable MapBasketItems(RepeatedField items) + public IEnumerable MapBasketItems(RepeatedField items) + { + return items.Select(x => new ApiModels.BasketItem() { - return items.Select(x => new ApiModels.BasketItem() - { - Id = x.Id, - ProductId = x.ProductId, - ProductName = x.ProductName, - UnitPrice = (decimal)x.UnitPrice, - OldUnitPrice = (decimal)x.OldUnitPrice, - Quantity = x.Quantity, - PictureUrl = x.PictureUrl, - }); - } + Id = x.Id, + ProductId = x.ProductId, + ProductName = x.ProductName, + UnitPrice = (decimal)x.UnitPrice, + OldUnitPrice = (decimal)x.OldUnitPrice, + Quantity = x.Quantity, + PictureUrl = x.PictureUrl, + }); } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Ordering/Ordering.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs index 55cb33c99..d886bf371 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs @@ -1,14 +1,10 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults -{ - using AspNetCore.Http; - using Microsoft.AspNetCore.Mvc; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults; - public class InternalServerErrorObjectResult : ObjectResult +public class InternalServerErrorObjectResult : ObjectResult +{ + public InternalServerErrorObjectResult(object error) + : base(error) { - public InternalServerErrorObjectResult(object error) - : base(error) - { - StatusCode = StatusCodes.Status500InternalServerError; - } + StatusCode = StatusCodes.Status500InternalServerError; } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs index bc7916188..dbf8cf97c 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs @@ -1,34 +1,27 @@ -using Microsoft.AspNetCore.Mvc.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Auth; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Auth +public class AuthorizationHeaderParameterOperationFilter : IOperationFilter { - public class AuthorizationHeaderParameterOperationFilter : IOperationFilter + public void Apply(OpenApiOperation operation, OperationFilterContext context) { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors; - var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter); - var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter); + var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors; + var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter); + var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter); - if (isAuthorized && !allowAnonymous) - { - if (operation.Parameters == null) - operation.Parameters = new List(); + if (isAuthorized && !allowAnonymous) + { + if (operation.Parameters == null) + operation.Parameters = new List(); - operation.Parameters.Add(new OpenApiParameter - { - Name = "Authorization", - In = ParameterLocation.Header, - Description = "access token", - Required = true - }); - } + operation.Parameters.Add(new OpenApiParameter + { + Name = "Authorization", + In = ParameterLocation.Header, + Description = "access token", + Required = true + }); } - } + } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/ApplicationModule.cs b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/ApplicationModule.cs index 1d8f45353..1ab775042 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/ApplicationModule.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/ApplicationModule.cs @@ -1,50 +1,38 @@ -using Autofac; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories; -using System.Reflection; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules -{ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules; - public class ApplicationModule - : Autofac.Module - { +public class ApplicationModule + : Autofac.Module +{ - public string QueriesConnectionString { get; } + public string QueriesConnectionString { get; } - public ApplicationModule(string qconstr) - { - QueriesConnectionString = qconstr; + public ApplicationModule(string qconstr) + { + QueriesConnectionString = qconstr; - } + } - protected override void Load(ContainerBuilder builder) - { + protected override void Load(ContainerBuilder builder) + { - builder.Register(c => new OrderQueries(QueriesConnectionString)) - .As() - .InstancePerLifetimeScope(); + builder.Register(c => new OrderQueries(QueriesConnectionString)) + .As() + .InstancePerLifetimeScope(); - builder.RegisterType() - .As() - .InstancePerLifetimeScope(); + builder.RegisterType() + .As() + .InstancePerLifetimeScope(); - builder.RegisterType() - .As() - .InstancePerLifetimeScope(); + builder.RegisterType() + .As() + .InstancePerLifetimeScope(); - builder.RegisterType() - .As() - .InstancePerLifetimeScope(); + builder.RegisterType() + .As() + .InstancePerLifetimeScope(); - builder.RegisterAssemblyTypes(typeof(CreateOrderCommandHandler).GetTypeInfo().Assembly) - .AsClosedTypesOf(typeof(IIntegrationEventHandler<>)); + builder.RegisterAssemblyTypes(typeof(CreateOrderCommandHandler).GetTypeInfo().Assembly) + .AsClosedTypesOf(typeof(IIntegrationEventHandler<>)); - } } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs index 91e9a5149..2d59f1730 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs @@ -1,47 +1,36 @@ -using Autofac; -using FluentValidation; -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Ordering.API.Application.Behaviors; -using Ordering.API.Application.DomainEventHandlers.OrderStartedEvent; -using Ordering.API.Application.Validations; -using System.Linq; -using System.Reflection; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.AutofacModules; + +public class MediatorModule : Autofac.Module { - public class MediatorModule : Autofac.Module + protected override void Load(ContainerBuilder builder) { - protected override void Load(ContainerBuilder builder) - { - builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly) - .AsImplementedInterfaces(); + builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly) + .AsImplementedInterfaces(); - // Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands - builder.RegisterAssemblyTypes(typeof(CreateOrderCommand).GetTypeInfo().Assembly) - .AsClosedTypesOf(typeof(IRequestHandler<,>)); + // Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands + builder.RegisterAssemblyTypes(typeof(CreateOrderCommand).GetTypeInfo().Assembly) + .AsClosedTypesOf(typeof(IRequestHandler<,>)); - // Register the DomainEventHandler classes (they implement INotificationHandler<>) in assembly holding the Domain Events - builder.RegisterAssemblyTypes(typeof(ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler).GetTypeInfo().Assembly) - .AsClosedTypesOf(typeof(INotificationHandler<>)); + // Register the DomainEventHandler classes (they implement INotificationHandler<>) in assembly holding the Domain Events + builder.RegisterAssemblyTypes(typeof(ValidateOrAddBuyerAggregateWhenOrderStartedDomainEventHandler).GetTypeInfo().Assembly) + .AsClosedTypesOf(typeof(INotificationHandler<>)); - // Register the Command's Validators (Validators based on FluentValidation library) - builder - .RegisterAssemblyTypes(typeof(CreateOrderCommandValidator).GetTypeInfo().Assembly) - .Where(t => t.IsClosedTypeOf(typeof(IValidator<>))) - .AsImplementedInterfaces(); + // Register the Command's Validators (Validators based on FluentValidation library) + builder + .RegisterAssemblyTypes(typeof(CreateOrderCommandValidator).GetTypeInfo().Assembly) + .Where(t => t.IsClosedTypeOf(typeof(IValidator<>))) + .AsImplementedInterfaces(); - builder.Register(context => - { - var componentContext = context.Resolve(); - return t => { object o; return componentContext.TryResolve(t, out o) ? o : null; }; - }); + builder.Register(context => + { + var componentContext = context.Resolve(); + return t => { object o; return componentContext.TryResolve(t, out o) ? o : null; }; + }); - builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>)); - builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>)); - builder.RegisterGeneric(typeof(TransactionBehaviour<,>)).As(typeof(IPipelineBehavior<,>)); + builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>)); + builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>)); + builder.RegisterGeneric(typeof(TransactionBehaviour<,>)).As(typeof(IPipelineBehavior<,>)); - } } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Factories/OrderingDbContextFactory.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Factories/OrderingDbContextFactory.cs index 56ec898af..9f05e610c 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Factories/OrderingDbContextFactory.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Factories/OrderingDbContextFactory.cs @@ -1,10 +1,4 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Microsoft.Extensions.Configuration; -using System.IO; - -namespace Ordering.API.Infrastructure.Factories +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Factories { public class OrderingDbContextFactory : IDesignTimeDbContextFactory { diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs index 34b897a40..b4689bf9a 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/AuthorizeCheckOperationFilter.cs @@ -1,36 +1,29 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Filters; -namespace Ordering.API.Infrastructure.Filters +public class AuthorizeCheckOperationFilter : IOperationFilter { - public class AuthorizeCheckOperationFilter : IOperationFilter + public void Apply(OpenApiOperation operation, OperationFilterContext context) { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - // Check for authorize attribute - var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || - context.MethodInfo.GetCustomAttributes(true).OfType().Any(); + // Check for authorize attribute + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - if (!hasAuthorize) return; + if (!hasAuthorize) return; - operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); - operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); + operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); - var oAuthScheme = new OpenApiSecurityScheme - { - Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } - }; + var oAuthScheme = new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } + }; - operation.Security = new List + operation.Security = new List + { + new() { - new OpenApiSecurityRequirement - { - [ oAuthScheme ] = new [] { "orderingapi" } - } - }; - } + [ oAuthScheme ] = new [] { "orderingapi" } + } + }; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs index 8b7587744..eef48c502 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs @@ -1,71 +1,60 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Filters +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Filters; + +public class HttpGlobalExceptionFilter : IExceptionFilter { - using AspNetCore.Mvc; - using global::Ordering.Domain.Exceptions; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Http; - using Microsoft.AspNetCore.Mvc.Filters; - using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.ActionResults; - using Microsoft.Extensions.Hosting; - using Microsoft.Extensions.Logging; - using System.Net; + private readonly IWebHostEnvironment env; + private readonly ILogger logger; - public class HttpGlobalExceptionFilter : IExceptionFilter + public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) { - private readonly IWebHostEnvironment env; - private readonly ILogger logger; + this.env = env; + this.logger = logger; + } - public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) - { - this.env = env; - this.logger = logger; - } + public void OnException(ExceptionContext context) + { + logger.LogError(new EventId(context.Exception.HResult), + context.Exception, + context.Exception.Message); - public void OnException(ExceptionContext context) + if (context.Exception.GetType() == typeof(OrderingDomainException)) { - logger.LogError(new EventId(context.Exception.HResult), - context.Exception, - context.Exception.Message); - - if (context.Exception.GetType() == typeof(OrderingDomainException)) + var problemDetails = new ValidationProblemDetails() { - var problemDetails = new ValidationProblemDetails() - { - Instance = context.HttpContext.Request.Path, - Status = StatusCodes.Status400BadRequest, - Detail = "Please refer to the errors property for additional details." - }; + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; - problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); + problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); - context.Result = new BadRequestObjectResult(problemDetails); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - else + context.Result = new BadRequestObjectResult(problemDetails); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + } + else + { + var json = new JsonErrorResponse { - var json = new JsonErrorResponse - { - Messages = new[] { "An error occur.Try it again." } - }; - - if (env.IsDevelopment()) - { - json.DeveloperMessage = context.Exception; - } + Messages = new[] { "An error occur.Try it again." } + }; - // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 - // It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information - context.Result = new InternalServerErrorObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + if (env.IsDevelopment()) + { + json.DeveloperMessage = context.Exception; } - context.ExceptionHandled = true; + + // Result asigned to a result object but in destiny the response is empty. This is a known bug of .net core 1.1 + // It will be fixed in .net core 1.1.2. See https://github.com/aspnet/Mvc/issues/5594 for more information + context.Result = new InternalServerErrorObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } + context.ExceptionHandled = true; + } - private class JsonErrorResponse - { - public string[] Messages { get; set; } + private class JsonErrorResponse + { + public string[] Messages { get; set; } - public object DeveloperMessage { get; set; } - } + public object DeveloperMessage { get; set; } } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs b/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs index 35b79e505..3c0aca009 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs @@ -1,191 +1,174 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; + +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; + +public class OrderingContextSeed { - using global::Ordering.API.Extensions; - using Microsoft.AspNetCore.Hosting; - using Microsoft.EntityFrameworkCore; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using Ordering.Infrastructure; - using Polly; - using Polly.Retry; - using System; - using System.Collections.Generic; - using System.Data.SqlClient; - using System.IO; - using System.Linq; - using System.Threading.Tasks; - - public class OrderingContextSeed + public async Task SeedAsync(OrderingContext context, IWebHostEnvironment env, IOptions settings, ILogger logger) { - public async Task SeedAsync(OrderingContext context, IWebHostEnvironment env, IOptions settings, ILogger logger) + var policy = CreatePolicy(logger, nameof(OrderingContextSeed)); + + await policy.ExecuteAsync(async () => { - var policy = CreatePolicy(logger, nameof(OrderingContextSeed)); - await policy.ExecuteAsync(async () => - { + var useCustomizationData = settings.Value + .UseCustomizationData; - var useCustomizationData = settings.Value - .UseCustomizationData; + var contentRootPath = env.ContentRootPath; - var contentRootPath = env.ContentRootPath; + using (context) + { + context.Database.Migrate(); - using (context) + if (!context.CardTypes.Any()) { - context.Database.Migrate(); - - if (!context.CardTypes.Any()) - { - context.CardTypes.AddRange(useCustomizationData - ? GetCardTypesFromFile(contentRootPath, logger) - : GetPredefinedCardTypes()); - - await context.SaveChangesAsync(); - } - - if (!context.OrderStatus.Any()) - { - context.OrderStatus.AddRange(useCustomizationData - ? GetOrderStatusFromFile(contentRootPath, logger) - : GetPredefinedOrderStatus()); - } + context.CardTypes.AddRange(useCustomizationData + ? GetCardTypesFromFile(contentRootPath, logger) + : GetPredefinedCardTypes()); await context.SaveChangesAsync(); } - }); - } - private IEnumerable GetCardTypesFromFile(string contentRootPath, ILogger log) - { - string csvFileCardTypes = Path.Combine(contentRootPath, "Setup", "CardTypes.csv"); + if (!context.OrderStatus.Any()) + { + context.OrderStatus.AddRange(useCustomizationData + ? GetOrderStatusFromFile(contentRootPath, logger) + : GetPredefinedOrderStatus()); + } - if (!File.Exists(csvFileCardTypes)) - { - return GetPredefinedCardTypes(); + await context.SaveChangesAsync(); } + }); + } - string[] csvheaders; - try - { - string[] requiredHeaders = { "CardType" }; - csvheaders = GetHeaders(requiredHeaders, csvFileCardTypes); - } - catch (Exception ex) - { - log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); - return GetPredefinedCardTypes(); - } + private IEnumerable GetCardTypesFromFile(string contentRootPath, ILogger log) + { + string csvFileCardTypes = Path.Combine(contentRootPath, "Setup", "CardTypes.csv"); - int id = 1; - return File.ReadAllLines(csvFileCardTypes) - .Skip(1) // skip header column - .SelectTry(x => CreateCardType(x, ref id)) - .OnCaughtException(ex => { log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) - .Where(x => x != null); + if (!File.Exists(csvFileCardTypes)) + { + return GetPredefinedCardTypes(); } - private CardType CreateCardType(string value, ref int id) + string[] csvheaders; + try { - if (String.IsNullOrEmpty(value)) - { - throw new Exception("Orderstatus is null or empty"); - } - - return new CardType(id++, value.Trim('"').Trim()); + string[] requiredHeaders = { "CardType" }; + csvheaders = GetHeaders(requiredHeaders, csvFileCardTypes); } - - private IEnumerable GetPredefinedCardTypes() + catch (Exception ex) { - return Enumeration.GetAll(); + log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); + return GetPredefinedCardTypes(); } - private IEnumerable GetOrderStatusFromFile(string contentRootPath, ILogger log) + int id = 1; + return File.ReadAllLines(csvFileCardTypes) + .Skip(1) // skip header column + .SelectTry(x => CreateCardType(x, ref id)) + .OnCaughtException(ex => { log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) + .Where(x => x != null); + } + + private CardType CreateCardType(string value, ref int id) + { + if (String.IsNullOrEmpty(value)) { - string csvFileOrderStatus = Path.Combine(contentRootPath, "Setup", "OrderStatus.csv"); + throw new Exception("Orderstatus is null or empty"); + } - if (!File.Exists(csvFileOrderStatus)) - { - return GetPredefinedOrderStatus(); - } + return new CardType(id++, value.Trim('"').Trim()); + } - string[] csvheaders; - try - { - string[] requiredHeaders = { "OrderStatus" }; - csvheaders = GetHeaders(requiredHeaders, csvFileOrderStatus); - } - catch (Exception ex) - { - log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); - return GetPredefinedOrderStatus(); - } + private IEnumerable GetPredefinedCardTypes() + { + return Enumeration.GetAll(); + } - int id = 1; - return File.ReadAllLines(csvFileOrderStatus) - .Skip(1) // skip header row - .SelectTry(x => CreateOrderStatus(x, ref id)) - .OnCaughtException(ex => { log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) - .Where(x => x != null); - } + private IEnumerable GetOrderStatusFromFile(string contentRootPath, ILogger log) + { + string csvFileOrderStatus = Path.Combine(contentRootPath, "Setup", "OrderStatus.csv"); - private OrderStatus CreateOrderStatus(string value, ref int id) + if (!File.Exists(csvFileOrderStatus)) { - if (String.IsNullOrEmpty(value)) - { - throw new Exception("Orderstatus is null or empty"); - } + return GetPredefinedOrderStatus(); + } - return new OrderStatus(id++, value.Trim('"').Trim().ToLowerInvariant()); + string[] csvheaders; + try + { + string[] requiredHeaders = { "OrderStatus" }; + csvheaders = GetHeaders(requiredHeaders, csvFileOrderStatus); + } + catch (Exception ex) + { + log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); + return GetPredefinedOrderStatus(); } - private IEnumerable GetPredefinedOrderStatus() + int id = 1; + return File.ReadAllLines(csvFileOrderStatus) + .Skip(1) // skip header row + .SelectTry(x => CreateOrderStatus(x, ref id)) + .OnCaughtException(ex => { log.LogError(ex, "EXCEPTION ERROR: {Message}", ex.Message); return null; }) + .Where(x => x != null); + } + + private OrderStatus CreateOrderStatus(string value, ref int id) + { + if (String.IsNullOrEmpty(value)) { - return new List() - { - OrderStatus.Submitted, - OrderStatus.AwaitingValidation, - OrderStatus.StockConfirmed, - OrderStatus.Paid, - OrderStatus.Shipped, - OrderStatus.Cancelled - }; + throw new Exception("Orderstatus is null or empty"); } - private string[] GetHeaders(string[] requiredHeaders, string csvfile) + return new OrderStatus(id++, value.Trim('"').Trim().ToLowerInvariant()); + } + + private IEnumerable GetPredefinedOrderStatus() + { + return new List() { - string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(','); + OrderStatus.Submitted, + OrderStatus.AwaitingValidation, + OrderStatus.StockConfirmed, + OrderStatus.Paid, + OrderStatus.Shipped, + OrderStatus.Cancelled + }; + } - if (csvheaders.Count() != requiredHeaders.Count()) - { - throw new Exception($"requiredHeader count '{ requiredHeaders.Count()}' is different then read header '{csvheaders.Count()}'"); - } + private string[] GetHeaders(string[] requiredHeaders, string csvfile) + { + string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(','); - foreach (var requiredHeader in requiredHeaders) + if (csvheaders.Count() != requiredHeaders.Count()) + { + throw new Exception($"requiredHeader count '{ requiredHeaders.Count()}' is different then read header '{csvheaders.Count()}'"); + } + + foreach (var requiredHeader in requiredHeaders) + { + if (!csvheaders.Contains(requiredHeader)) { - if (!csvheaders.Contains(requiredHeader)) - { - throw new Exception($"does not contain required header '{requiredHeader}'"); - } + throw new Exception($"does not contain required header '{requiredHeader}'"); } - - return csvheaders; } + return csvheaders; + } - private AsyncRetryPolicy CreatePolicy(ILogger logger, string prefix, int retries = 3) - { - return Policy.Handle(). - WaitAndRetryAsync( - retryCount: retries, - sleepDurationProvider: retry => TimeSpan.FromSeconds(5), - onRetry: (exception, timeSpan, retry, ctx) => - { - logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries); - } - ); - } + + private AsyncRetryPolicy CreatePolicy(ILogger logger, string prefix, int retries = 3) + { + return Policy.Handle(). + WaitAndRetryAsync( + retryCount: retries, + sleepDurationProvider: retry => TimeSpan.FromSeconds(5), + onRetry: (exception, timeSpan, retry, ctx) => + { + logger.LogWarning(exception, "[{prefix}] Exception {ExceptionType} with message {Message} detected on attempt {retry} of {retries}", prefix, exception.GetType().Name, exception.Message, retry, retries); + } + ); } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Services/IIdentityService.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Services/IIdentityService.cs index e51452d7d..3b055f0ab 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Services/IIdentityService.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Services/IIdentityService.cs @@ -1,9 +1,9 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; + +public interface IIdentityService { - public interface IIdentityService - { - string GetUserIdentity(); + string GetUserIdentity(); - string GetUserName(); - } + string GetUserName(); } + diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Services/IdentityService.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Services/IdentityService.cs index 4dab338c4..0849805e2 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Services/IdentityService.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Services/IdentityService.cs @@ -1,26 +1,21 @@ - -using Microsoft.AspNetCore.Http; -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; -namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services +public class IdentityService : IIdentityService { - public class IdentityService : IIdentityService - { - private IHttpContextAccessor _context; + private IHttpContextAccessor _context; - public IdentityService(IHttpContextAccessor context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + public IdentityService(IHttpContextAccessor context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } - public string GetUserIdentity() - { - return _context.HttpContext.User.FindFirst("sub").Value; - } + public string GetUserIdentity() + { + return _context.HttpContext.User.FindFirst("sub").Value; + } - public string GetUserName() - { - return _context.HttpContext.User.Identity.Name; - } + public string GetUserName() + { + return _context.HttpContext.User.Identity.Name; } } diff --git a/src/Services/Ordering/Ordering.API/Ordering.API.csproj b/src/Services/Ordering/Ordering.API/Ordering.API.csproj index 46b07ca29..5d779ffc0 100644 --- a/src/Services/Ordering/Ordering.API/Ordering.API.csproj +++ b/src/Services/Ordering/Ordering.API/Ordering.API.csproj @@ -1,13 +1,12 @@  - net5.0 + net6.0 aspnet-Ordering.API-20161122013547 $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; ..\..\..\..\docker-compose.dcproj false - true - preview + true @@ -37,38 +36,40 @@ - + - + + + - + - - - - - - + + + + + + - - - - + + - - - - - - - + + + + + + + + + PreserveNewest diff --git a/src/Services/Ordering/Ordering.API/OrderingSettings.cs b/src/Services/Ordering/Ordering.API/OrderingSettings.cs index 7459bfd1c..93cc94b92 100644 --- a/src/Services/Ordering/Ordering.API/OrderingSettings.cs +++ b/src/Services/Ordering/Ordering.API/OrderingSettings.cs @@ -1,15 +1,14 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API +namespace Microsoft.eShopOnContainers.Services.Ordering.API; + +public class OrderingSettings { - public class OrderingSettings - { - public bool UseCustomizationData { get; set; } + public bool UseCustomizationData { get; set; } - public string ConnectionString { get; set; } + public string ConnectionString { get; set; } - public string EventBusConnection { get; set; } + public string EventBusConnection { get; set; } - public int GracePeriodTime { get; set; } + public int GracePeriodTime { get; set; } - public int CheckUpdateTime { get; set; } - } + public int CheckUpdateTime { get; set; } } diff --git a/src/Services/Ordering/Ordering.API/Program.cs b/src/Services/Ordering/Ordering.API/Program.cs index 0a42cbba1..bc5223a24 100644 --- a/src/Services/Ordering/Ordering.API/Program.cs +++ b/src/Services/Ordering/Ordering.API/Program.cs @@ -1,20 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.Services.Ordering.API; -using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Serilog; -using System; -using System.IO; -using System.Net; - -var configuration = GetConfiguration(); +var configuration = GetConfiguration(); Log.Logger = CreateSerilogLogger(configuration); @@ -100,10 +84,11 @@ IConfiguration GetConfiguration() if (config.GetValue("UseVault", false)) { - builder.AddAzureKeyVault( - $"https://{config["Vault:Name"]}.vault.azure.net/", + TokenCredential credential = new ClientSecretCredential( + config["Vault:TenantId"], config["Vault:ClientId"], config["Vault:ClientSecret"]); + builder.AddAzureKeyVault(new Uri($"https://{config["Vault:Name"]}.vault.azure.net/"), credential); } return builder.Build(); @@ -116,7 +101,7 @@ IConfiguration GetConfiguration() return (port, grpcPort); } -public class Program +public partial class Program { public static string Namespace = typeof(Startup).Namespace; diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index d55876203..501a55361 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -1,430 +1,390 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.API +namespace Microsoft.eShopOnContainers.Services.Ordering.API; + +public class Startup { - using AspNetCore.Http; - using Autofac; - using Autofac.Extensions.DependencyInjection; - using global::Ordering.API.Application.IntegrationEvents; - using global::Ordering.API.Application.IntegrationEvents.Events; - using global::Ordering.API.Infrastructure.Filters; - using GrpcOrdering; - using HealthChecks.UI.Client; - using Infrastructure.AutofacModules; - using Infrastructure.Filters; - using Infrastructure.Services; - using Microsoft.AspNetCore.Builder; - using Microsoft.AspNetCore.Diagnostics.HealthChecks; - using Microsoft.AspNetCore.Hosting; - using Microsoft.AspNetCore.Mvc; - using Microsoft.Azure.ServiceBus; - using Microsoft.EntityFrameworkCore; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; - using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; - using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; - using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; - using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Extensions.Diagnostics.HealthChecks; - using Microsoft.Extensions.Logging; - using Microsoft.OpenApi.Models; - using Ordering.Infrastructure; - using RabbitMQ.Client; - using System; - using System.Collections.Generic; - using System.Data.Common; - using System.IdentityModel.Tokens.Jwt; - using System.IO; - using System.Reflection; - - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - public virtual IServiceProvider ConfigureServices(IServiceCollection services) - { - services - .AddGrpc(options => - { - options.EnableDetailedErrors = true; - }) - .Services - .AddApplicationInsights(Configuration) - .AddCustomMvc() - .AddHealthChecks(Configuration) - .AddCustomDbContext(Configuration) - .AddCustomSwagger(Configuration) - .AddCustomIntegrations(Configuration) - .AddCustomConfiguration(Configuration) - .AddEventBus(Configuration) - .AddCustomAuthentication(Configuration); - //configure autofac - - var container = new ContainerBuilder(); - container.Populate(services); - - container.RegisterModule(new MediatorModule()); - container.RegisterModule(new ApplicationModule(Configuration["ConnectionString"])); - - return new AutofacServiceProvider(container.Build()); - } + public virtual IServiceProvider ConfigureServices(IServiceCollection services) + { + services + .AddGrpc(options => + { + options.EnableDetailedErrors = true; + }) + .Services + .AddApplicationInsights(Configuration) + .AddCustomMvc() + .AddHealthChecks(Configuration) + .AddCustomDbContext(Configuration) + .AddCustomSwagger(Configuration) + .AddCustomIntegrations(Configuration) + .AddCustomConfiguration(Configuration) + .AddEventBus(Configuration) + .AddCustomAuthentication(Configuration); + //configure autofac + + var container = new ContainerBuilder(); + container.Populate(services); + + container.RegisterModule(new MediatorModule()); + container.RegisterModule(new ApplicationModule(Configuration["ConnectionString"])); + + return new AutofacServiceProvider(container.Build()); + } - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) + { + //loggerFactory.AddAzureWebAppDiagnostics(); + //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) { - //loggerFactory.AddAzureWebAppDiagnostics(); - //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); + } - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) + app.UseSwagger() + .UseSwaggerUI(c => { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); - app.UsePathBase(pathBase); - } - - app.UseSwagger() - .UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Ordering.API V1"); - c.OAuthClientId("orderingswaggerui"); - c.OAuthAppName("Ordering Swagger UI"); - }); - - app.UseRouting(); - app.UseCors("CorsPolicy"); - ConfigureAuth(app); - - app.UseEndpoints(endpoints => + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Ordering.API V1"); + c.OAuthClientId("orderingswaggerui"); + c.OAuthAppName("Ordering Swagger UI"); + }); + + app.UseRouting(); + app.UseCors("CorsPolicy"); + ConfigureAuth(app); + + app.UseEndpoints(endpoints => + { + endpoints.MapGrpcService(); + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapGet("/_proto/", async ctx => { - endpoints.MapGrpcService(); - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapGet("/_proto/", async ctx => + ctx.Response.ContentType = "text/plain"; + using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read); + using var sr = new StreamReader(fs); + while (!sr.EndOfStream) { - ctx.Response.ContentType = "text/plain"; - using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read); - using var sr = new StreamReader(fs); - while (!sr.EndOfStream) + var line = await sr.ReadLineAsync(); + if (line != "/* >>" || line != "<< */") { - var line = await sr.ReadLineAsync(); - if (line != "/* >>" || line != "<< */") - { - await ctx.Response.WriteAsync(line); - } + await ctx.Response.WriteAsync(line); } - }); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); + } + }); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions + { + Predicate = r => r.Name.Contains("self") }); + }); - ConfigureEventBus(app); - } + ConfigureEventBus(app); + } - private void ConfigureEventBus(IApplicationBuilder app) - { - var eventBus = app.ApplicationServices.GetRequiredService(); - - eventBus.Subscribe>(); - eventBus.Subscribe>(); - eventBus.Subscribe>(); - eventBus.Subscribe>(); - eventBus.Subscribe>(); - eventBus.Subscribe>(); - } + private void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + + eventBus.Subscribe>(); + eventBus.Subscribe>(); + eventBus.Subscribe>(); + eventBus.Subscribe>(); + eventBus.Subscribe>(); + eventBus.Subscribe>(); + } - protected virtual void ConfigureAuth(IApplicationBuilder app) - { - app.UseAuthentication(); - app.UseAuthorization(); - } + protected virtual void ConfigureAuth(IApplicationBuilder app) + { + app.UseAuthentication(); + app.UseAuthorization(); } +} - static class CustomExtensionsMethods +static class CustomExtensionsMethods +{ + public static IServiceCollection AddApplicationInsights(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddApplicationInsights(this IServiceCollection services, IConfiguration configuration) - { - services.AddApplicationInsightsTelemetry(configuration); - services.AddApplicationInsightsKubernetesEnricher(); + services.AddApplicationInsightsTelemetry(configuration); + services.AddApplicationInsightsKubernetesEnricher(); - return services; - } + return services; + } - public static IServiceCollection AddCustomMvc(this IServiceCollection services) - { - // Add framework services. - services.AddControllers(options => - { - options.Filters.Add(typeof(HttpGlobalExceptionFilter)); - }) - // Added for functional tests - .AddApplicationPart(typeof(OrdersController).Assembly) - .AddNewtonsoftJson() - .SetCompatibilityVersion(CompatibilityVersion.Version_3_0) - ; - - services.AddCors(options => + public static IServiceCollection AddCustomMvc(this IServiceCollection services) + { + // Add framework services. + services.AddControllers(options => { - options.AddPolicy("CorsPolicy", - builder => builder - .SetIsOriginAllowed((host) => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + }) + // Added for functional tests + .AddApplicationPart(typeof(OrdersController).Assembly) + .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true) + .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } - return services; - } + public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) + { + var hcBuilder = services.AddHealthChecks(); - public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) - { - var hcBuilder = services.AddHealthChecks(); + hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); - hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); + hcBuilder + .AddSqlServer( + configuration["ConnectionString"], + name: "OrderingDB-check", + tags: new string[] { "orderingdb" }); + if (configuration.GetValue("AzureServiceBusEnabled")) + { hcBuilder - .AddSqlServer( - configuration["ConnectionString"], - name: "OrderingDB-check", - tags: new string[] { "orderingdb" }); - - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "ordering-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "ordering-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } - - return services; + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "ordering-servicebus-check", + tags: new string[] { "servicebus" }); } - - public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + else { - services.AddDbContext(options => - { - options.UseSqlServer(configuration["ConnectionString"], - sqlServerOptionsAction: sqlOptions => - { - sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - }); - }, - ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) - ); - - services.AddDbContext(options => - { - options.UseSqlServer(configuration["ConnectionString"], - sqlServerOptionsAction: sqlOptions => - { - sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - }); - }); - - return services; + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "ordering-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); } - public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IConfiguration configuration) + return services; + } + + public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + { + services.AddDbContext(options => + { + options.UseSqlServer(configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }, + ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) + ); + + services.AddDbContext(options => { - services.AddSwaggerGen(options => + options.UseSqlServer(configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }); + + return services; + } + + public static IServiceCollection AddCustomSwagger(this IServiceCollection services, IConfiguration configuration) + { + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "eShopOnContainers - Ordering HTTP API", - Version = "v1", - Description = "The Ordering Service HTTP API" - }); - options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + Title = "eShopOnContainers - Ordering HTTP API", + Version = "v1", + Description = "The Ordering Service HTTP API" + }); + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() + Implicit = new OpenApiOAuthFlow() { - Implicit = new OpenApiOAuthFlow() + AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), + TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), + Scopes = new Dictionary() { - AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), - TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), - Scopes = new Dictionary() - { - { "orders", "Ordering API" } - } + { "orders", "Ordering API" } } } - }); - - options.OperationFilter(); + } }); - return services; - } + options.OperationFilter(); + }); - public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddTransient(); - services.AddTransient>( - sp => (DbConnection c) => new IntegrationEventLogService(c)); + return services; + } - services.AddTransient(); + public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(); + services.AddTransient(); + services.AddTransient>( + sp => (DbConnection c) => new IntegrationEventLogService(c)); - if (configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var serviceBusConnectionString = configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - var subscriptionClientName = configuration["SubscriptionClientName"]; - - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); - }); - } - else + services.AddTransient(); + + if (configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); + var serviceBusConnectionString = configuration["EventBusConnection"]; + var subscriptionClientName = configuration["SubscriptionClientName"]; - var factory = new ConnectionFactory() - { - HostName = configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; + return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); + }); + } + else + { + services.AddSingleton(sp => + { + var logger = sp.GetRequiredService>(); - if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) - { - factory.UserName = configuration["EventBusUserName"]; - } - if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) - { - factory.Password = configuration["EventBusPassword"]; - } + var factory = new ConnectionFactory() + { + HostName = configuration["EventBusConnection"], + DispatchConsumersAsync = true + }; - var retryCount = 5; - if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(configuration["EventBusRetryCount"]); - } + if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) + { + factory.UserName = configuration["EventBusUserName"]; + } + + if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) + { + factory.Password = configuration["EventBusPassword"]; + } - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } - return services; + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); + }); } - public static IServiceCollection AddCustomConfiguration(this IServiceCollection services, IConfiguration configuration) + return services; + } + + public static IServiceCollection AddCustomConfiguration(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + services.Configure(configuration); + services.Configure(options => { - services.AddOptions(); - services.Configure(configuration); - services.Configure(options => + options.InvalidModelStateResponseFactory = context => { - options.InvalidModelStateResponseFactory = context => + var problemDetails = new ValidationProblemDetails(context.ModelState) { - var problemDetails = new ValidationProblemDetails(context.ModelState) - { - Instance = context.HttpContext.Request.Path, - Status = StatusCodes.Status400BadRequest, - Detail = "Please refer to the errors property for additional details." - }; + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; - return new BadRequestObjectResult(problemDetails) - { - ContentTypes = { "application/problem+json", "application/problem+xml" } - }; + return new BadRequestObjectResult(problemDetails) + { + ContentTypes = { "application/problem+json", "application/problem+xml" } }; - }); + }; + }); - return services; - } + return services; + } - public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + { + if (configuration.GetValue("AzureServiceBusEnabled")) { - if (configuration.GetValue("AzureServiceBusEnabled")) + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, iLifetimeScope); - }); - } - else + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); + }); + } + else + { + services.AddSingleton(sp => { - services.AddSingleton(sp => + var subscriptionClientName = configuration["SubscriptionClientName"]; + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) { - var subscriptionClientName = configuration["SubscriptionClientName"]; - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(configuration["EventBusRetryCount"]); - } + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } - services.AddSingleton(); + services.AddSingleton(); - return services; - } + return services; + } - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) - { - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + // prevent from mapping "sub" claim to nameidentifier. + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - var identityUrl = configuration.GetValue("IdentityUrl"); + var identityUrl = configuration.GetValue("IdentityUrl"); - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme; + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "orders"; - }); + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "orders"; + }); - return services; - } + return services; } -} +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/appsettings.json b/src/Services/Ordering/Ordering.API/appsettings.json index 4ef8f6ac4..9c7f07ec1 100644 --- a/src/Services/Ordering/Ordering.API/appsettings.json +++ b/src/Services/Ordering/Ordering.API/appsettings.json @@ -26,7 +26,7 @@ "UseVault": false, "Vault": { "Name": "eshop", - "ClientId": "your-clien-id", + "ClientId": "your-client-id", "ClientSecret": "your-client-secret" } } diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile index ea95935ab..0a5ce8f0c 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Extensions/CustomExtensionMethods.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Extensions/CustomExtensionMethods.cs index ffdf68161..b7164734e 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Extensions/CustomExtensionMethods.cs +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Extensions/CustomExtensionMethods.cs @@ -1,5 +1,5 @@ using Autofac; -using Microsoft.Azure.ServiceBus; +using Azure.Messaging.ServiceBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; @@ -54,9 +54,8 @@ namespace Ordering.BackgroundTasks.Extensions services.AddSingleton(sp => { var serviceBusConnectionString = configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); + return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); }); services.AddSingleton(sp => @@ -65,8 +64,9 @@ namespace Ordering.BackgroundTasks.Extensions var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = configuration["SubscriptionClientName"]; - return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, iLifetimeScope); + return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); }); } else diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj index 4e10783b2..617ccda32 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj @@ -1,11 +1,10 @@  - net5.0 + net6.0 dotnet-Ordering.BackgroundTasks-9D3E1DD6-405B-447F-8AAB-1708B36D260E false - Linux - preview + Linux diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs b/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs index b53437d9b..9f00f3f60 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Services/GracePeriodManagerService.cs @@ -63,24 +63,22 @@ namespace Ordering.BackgroundTasks.Services { IEnumerable orderIds = new List(); - using (var conn = new SqlConnection(_settings.ConnectionString)) + using var conn = new SqlConnection(_settings.ConnectionString); + try { - try - { - conn.Open(); - orderIds = conn.Query( - @"SELECT Id FROM [ordering].[orders] - WHERE DATEDIFF(minute, [OrderDate], GETDATE()) >= @GracePeriodTime - AND [OrderStatusId] = 1", - new { _settings.GracePeriodTime }); - } - catch (SqlException exception) - { - _logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message); - } - + conn.Open(); + orderIds = conn.Query( + @"SELECT Id FROM [ordering].[orders] + WHERE DATEDIFF(minute, [OrderDate], GETDATE()) >= @GracePeriodTime + AND [OrderStatusId] = 1", + new { _settings.GracePeriodTime }); + } + catch (SqlException exception) + { + _logger.LogCritical(exception, "FATAL ERROR: Database connections could not be opened: {Message}", exception.Message); } + return orderIds; } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs index a3de10052..e959227bf 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs @@ -1,55 +1,48 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using Ordering.Domain.Events; -using System; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate +public class Buyer + : Entity, IAggregateRoot { - public class Buyer - : Entity, IAggregateRoot - { - public string IdentityGuid { get; private set; } + public string IdentityGuid { get; private set; } - public string Name { get; private set; } + public string Name { get; private set; } - private List _paymentMethods; + private List _paymentMethods; - public IEnumerable PaymentMethods => _paymentMethods.AsReadOnly(); + public IEnumerable PaymentMethods => _paymentMethods.AsReadOnly(); - protected Buyer() - { + protected Buyer() + { - _paymentMethods = new List(); - } + _paymentMethods = new List(); + } - public Buyer(string identity, string name) : this() - { - IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity)); - Name = !string.IsNullOrWhiteSpace(name) ? name : throw new ArgumentNullException(nameof(name)); - } + public Buyer(string identity, string name) : this() + { + IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity)); + Name = !string.IsNullOrWhiteSpace(name) ? name : throw new ArgumentNullException(nameof(name)); + } - public PaymentMethod VerifyOrAddPaymentMethod( - int cardTypeId, string alias, string cardNumber, - string securityNumber, string cardHolderName, DateTime expiration, int orderId) - { - var existingPayment = _paymentMethods - .SingleOrDefault(p => p.IsEqualTo(cardTypeId, cardNumber, expiration)); + public PaymentMethod VerifyOrAddPaymentMethod( + int cardTypeId, string alias, string cardNumber, + string securityNumber, string cardHolderName, DateTime expiration, int orderId) + { + var existingPayment = _paymentMethods + .SingleOrDefault(p => p.IsEqualTo(cardTypeId, cardNumber, expiration)); - if (existingPayment != null) - { - AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, existingPayment, orderId)); + if (existingPayment != null) + { + AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, existingPayment, orderId)); - return existingPayment; - } + return existingPayment; + } - var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); + var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); - _paymentMethods.Add(payment); + _paymentMethods.Add(payment); - AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, payment, orderId)); + AddDomainEvent(new BuyerAndPaymentMethodVerifiedDomainEvent(this, payment, orderId)); - return payment; - } + return payment; } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs index 3053cb678..52074c6d9 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/CardType.cs @@ -1,21 +1,20 @@ using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; + +/// +/// Card type class should be marked as abstract with protected constructor to encapsulate known enum types +/// this is currently not possible as OrderingContextSeed uses this constructor to load cardTypes from csv file +/// +public class CardType + : Enumeration { - /// - /// Card type class should be marked as abstract with protected constructor to encapsulate known enum types - /// this is currently not possible as OrderingContextSeed uses this constructor to load cardTypes from csv file - /// - public class CardType - : Enumeration - { - public static CardType Amex = new CardType(1, "Amex"); - public static CardType Visa = new CardType(2, "Visa"); - public static CardType MasterCard = new CardType(3, "MasterCard"); + public static CardType Amex = new(1, nameof(Amex)); + public static CardType Visa = new(2, nameof(Visa)); + public static CardType MasterCard = new(3, nameof(MasterCard)); - public CardType(int id, string name) - : base(id, name) - { - } + public CardType(int id, string name) + : base(id, name) + { } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/IBuyerRepository.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/IBuyerRepository.cs index 197f725f6..a241e7dbd 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/IBuyerRepository.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/IBuyerRepository.cs @@ -1,16 +1,13 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate -{ - //This is just the RepositoryContracts or Interface defined at the Domain Layer - //as requisite for the Buyer Aggregate +//This is just the RepositoryContracts or Interface defined at the Domain Layer +//as requisite for the Buyer Aggregate - public interface IBuyerRepository : IRepository - { - Buyer Add(Buyer buyer); - Buyer Update(Buyer buyer); - Task FindAsync(string BuyerIdentityGuid); - Task FindByIdAsync(string id); - } +public interface IBuyerRepository : IRepository +{ + Buyer Add(Buyer buyer); + Buyer Update(Buyer buyer); + Task FindAsync(string BuyerIdentityGuid); + Task FindByIdAsync(string id); } + diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/PaymentMethod.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/PaymentMethod.cs index bd245d1a8..e4e490488 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/PaymentMethod.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/PaymentMethod.cs @@ -1,46 +1,41 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using Ordering.Domain.Exceptions; -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate +public class PaymentMethod + : Entity { - public class PaymentMethod - : Entity - { - private string _alias; - private string _cardNumber; - private string _securityNumber; - private string _cardHolderName; - private DateTime _expiration; - - private int _cardTypeId; - public CardType CardType { get; private set; } + private string _alias; + private string _cardNumber; + private string _securityNumber; + private string _cardHolderName; + private DateTime _expiration; + private int _cardTypeId; + public CardType CardType { get; private set; } - protected PaymentMethod() { } - public PaymentMethod(int cardTypeId, string alias, string cardNumber, string securityNumber, string cardHolderName, DateTime expiration) - { + protected PaymentMethod() { } - _cardNumber = !string.IsNullOrWhiteSpace(cardNumber) ? cardNumber : throw new OrderingDomainException(nameof(cardNumber)); - _securityNumber = !string.IsNullOrWhiteSpace(securityNumber) ? securityNumber : throw new OrderingDomainException(nameof(securityNumber)); - _cardHolderName = !string.IsNullOrWhiteSpace(cardHolderName) ? cardHolderName : throw new OrderingDomainException(nameof(cardHolderName)); - - if (expiration < DateTime.UtcNow) - { - throw new OrderingDomainException(nameof(expiration)); - } + public PaymentMethod(int cardTypeId, string alias, string cardNumber, string securityNumber, string cardHolderName, DateTime expiration) + { - _alias = alias; - _expiration = expiration; - _cardTypeId = cardTypeId; - } + _cardNumber = !string.IsNullOrWhiteSpace(cardNumber) ? cardNumber : throw new OrderingDomainException(nameof(cardNumber)); + _securityNumber = !string.IsNullOrWhiteSpace(securityNumber) ? securityNumber : throw new OrderingDomainException(nameof(securityNumber)); + _cardHolderName = !string.IsNullOrWhiteSpace(cardHolderName) ? cardHolderName : throw new OrderingDomainException(nameof(cardHolderName)); - public bool IsEqualTo(int cardTypeId, string cardNumber, DateTime expiration) + if (expiration < DateTime.UtcNow) { - return _cardTypeId == cardTypeId - && _cardNumber == cardNumber - && _expiration == expiration; + throw new OrderingDomainException(nameof(expiration)); } + + _alias = alias; + _expiration = expiration; + _cardTypeId = cardTypeId; + } + + public bool IsEqualTo(int cardTypeId, string cardNumber, DateTime expiration) + { + return _cardTypeId == cardTypeId + && _cardNumber == cardNumber + && _expiration == expiration; } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Address.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Address.cs index e2c78094d..c58f81b16 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Address.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Address.cs @@ -1,36 +1,33 @@ using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; -using System; -using System.Collections.Generic; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + +public class Address : ValueObject { - public class Address : ValueObject - { - public String Street { get; private set; } - public String City { get; private set; } - public String State { get; private set; } - public String Country { get; private set; } - public String ZipCode { get; private set; } + public String Street { get; private set; } + public String City { get; private set; } + public String State { get; private set; } + public String Country { get; private set; } + public String ZipCode { get; private set; } - public Address() { } + public Address() { } - public Address(string street, string city, string state, string country, string zipcode) - { - Street = street; - City = city; - State = state; - Country = country; - ZipCode = zipcode; - } + public Address(string street, string city, string state, string country, string zipcode) + { + Street = street; + City = city; + State = state; + Country = country; + ZipCode = zipcode; + } - protected override IEnumerable GetEqualityComponents() - { - // Using a yield return statement to return each element one at a time - yield return Street; - yield return City; - yield return State; - yield return Country; - yield return ZipCode; - } + protected override IEnumerable GetEqualityComponents() + { + // Using a yield return statement to return each element one at a time + yield return Street; + yield return City; + yield return State; + yield return Country; + yield return ZipCode; } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs index a4e298cd7..af72ed88f 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/IOrderRepository.cs @@ -1,17 +1,13 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate -{ - //This is just the RepositoryContracts or Interface defined at the Domain Layer - //as requisite for the Order Aggregate +//This is just the RepositoryContracts or Interface defined at the Domain Layer +//as requisite for the Order Aggregate - public interface IOrderRepository : IRepository - { - Order Add(Order order); +public interface IOrderRepository : IRepository +{ + Order Add(Order order); - void Update(Order order); + void Update(Order order); - Task GetAsync(int orderId); - } + Task GetAsync(int orderId); } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs index 897a08592..81a67324b 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -1,202 +1,195 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using Ordering.Domain.Events; -using Ordering.Domain.Exceptions; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate +using Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; + +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + +public class Order + : Entity, IAggregateRoot { - public class Order - : Entity, IAggregateRoot - { - // DDD Patterns comment - // Using private fields, allowed since EF Core 1.1, is a much better encapsulation - // aligned with DDD Aggregates and Domain Entities (Instead of properties and property collections) - private DateTime _orderDate; + // DDD Patterns comment + // Using private fields, allowed since EF Core 1.1, is a much better encapsulation + // aligned with DDD Aggregates and Domain Entities (Instead of properties and property collections) + private DateTime _orderDate; - // Address is a Value Object pattern example persisted as EF Core 2.0 owned entity - public Address Address { get; private set; } + // Address is a Value Object pattern example persisted as EF Core 2.0 owned entity + public Address Address { get; private set; } - public int? GetBuyerId => _buyerId; - private int? _buyerId; + public int? GetBuyerId => _buyerId; + private int? _buyerId; - public OrderStatus OrderStatus { get; private set; } - private int _orderStatusId; + public OrderStatus OrderStatus { get; private set; } + private int _orderStatusId; - private string _description; + private string _description; - // Draft orders have this set to true. Currently we don't check anywhere the draft status of an Order, but we could do it if needed - private bool _isDraft; + // Draft orders have this set to true. Currently we don't check anywhere the draft status of an Order, but we could do it if needed + private bool _isDraft; - // DDD Patterns comment - // Using a private collection field, better for DDD Aggregate's encapsulation - // so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection, - // but only through the method OrderAggrergateRoot.AddOrderItem() which includes behaviour. - private readonly List _orderItems; - public IReadOnlyCollection OrderItems => _orderItems; + // DDD Patterns comment + // Using a private collection field, better for DDD Aggregate's encapsulation + // so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection, + // but only through the method OrderAggrergateRoot.AddOrderItem() which includes behaviour. + private readonly List _orderItems; + public IReadOnlyCollection OrderItems => _orderItems; - private int? _paymentMethodId; + private int? _paymentMethodId; - public static Order NewDraft() - { - var order = new Order(); - order._isDraft = true; - return order; - } + public static Order NewDraft() + { + var order = new Order(); + order._isDraft = true; + return order; + } - protected Order() - { - _orderItems = new List(); - _isDraft = false; - } + protected Order() + { + _orderItems = new List(); + _isDraft = false; + } - public Order(string userId, string userName, Address address, int cardTypeId, string cardNumber, string cardSecurityNumber, - string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null) : this() - { - _buyerId = buyerId; - _paymentMethodId = paymentMethodId; - _orderStatusId = OrderStatus.Submitted.Id; - _orderDate = DateTime.UtcNow; - Address = address; - - // Add the OrderStarterDomainEvent to the domain events collection - // to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ] - AddOrderStartedDomainEvent(userId, userName, cardTypeId, cardNumber, - cardSecurityNumber, cardHolderName, cardExpiration); - } + public Order(string userId, string userName, Address address, int cardTypeId, string cardNumber, string cardSecurityNumber, + string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null) : this() + { + _buyerId = buyerId; + _paymentMethodId = paymentMethodId; + _orderStatusId = OrderStatus.Submitted.Id; + _orderDate = DateTime.UtcNow; + Address = address; + + // Add the OrderStarterDomainEvent to the domain events collection + // to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ] + AddOrderStartedDomainEvent(userId, userName, cardTypeId, cardNumber, + cardSecurityNumber, cardHolderName, cardExpiration); + } - // DDD Patterns comment - // This Order AggregateRoot's method "AddOrderitem()" should be the only way to add Items to the Order, - // so any behavior (discounts, etc.) and validations are controlled by the AggregateRoot - // in order to maintain consistency between the whole Aggregate. - public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1) + // DDD Patterns comment + // This Order AggregateRoot's method "AddOrderitem()" should be the only way to add Items to the Order, + // so any behavior (discounts, etc.) and validations are controlled by the AggregateRoot + // in order to maintain consistency between the whole Aggregate. + public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1) + { + var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId) + .SingleOrDefault(); + + if (existingOrderForProduct != null) { - var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId) - .SingleOrDefault(); + //if previous line exist modify it with higher discount and units.. - if (existingOrderForProduct != null) + if (discount > existingOrderForProduct.GetCurrentDiscount()) { - //if previous line exist modify it with higher discount and units.. - - if (discount > existingOrderForProduct.GetCurrentDiscount()) - { - existingOrderForProduct.SetNewDiscount(discount); - } - - existingOrderForProduct.AddUnits(units); + existingOrderForProduct.SetNewDiscount(discount); } - else - { - //add validated new order item - var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); - _orderItems.Add(orderItem); - } + existingOrderForProduct.AddUnits(units); } - - public void SetPaymentId(int id) + else { - _paymentMethodId = id; - } + //add validated new order item - public void SetBuyerId(int id) - { - _buyerId = id; + var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); + _orderItems.Add(orderItem); } + } + + public void SetPaymentId(int id) + { + _paymentMethodId = id; + } - public void SetAwaitingValidationStatus() + public void SetBuyerId(int id) + { + _buyerId = id; + } + + public void SetAwaitingValidationStatus() + { + if (_orderStatusId == OrderStatus.Submitted.Id) { - if (_orderStatusId == OrderStatus.Submitted.Id) - { - AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); - _orderStatusId = OrderStatus.AwaitingValidation.Id; - } + AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems)); + _orderStatusId = OrderStatus.AwaitingValidation.Id; } + } - public void SetStockConfirmedStatus() + public void SetStockConfirmedStatus() + { + if (_orderStatusId == OrderStatus.AwaitingValidation.Id) { - if (_orderStatusId == OrderStatus.AwaitingValidation.Id) - { - AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); + AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id)); - _orderStatusId = OrderStatus.StockConfirmed.Id; - _description = "All the items were confirmed with available stock."; - } + _orderStatusId = OrderStatus.StockConfirmed.Id; + _description = "All the items were confirmed with available stock."; } + } - public void SetPaidStatus() + public void SetPaidStatus() + { + if (_orderStatusId == OrderStatus.StockConfirmed.Id) { - if (_orderStatusId == OrderStatus.StockConfirmed.Id) - { - AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); + AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems)); - _orderStatusId = OrderStatus.Paid.Id; - _description = "The payment was performed at a simulated \"American Bank checking bank account ending on XX35071\""; - } + _orderStatusId = OrderStatus.Paid.Id; + _description = "The payment was performed at a simulated \"American Bank checking bank account ending on XX35071\""; } + } - public void SetShippedStatus() + public void SetShippedStatus() + { + if (_orderStatusId != OrderStatus.Paid.Id) { - if (_orderStatusId != OrderStatus.Paid.Id) - { - StatusChangeException(OrderStatus.Shipped); - } - - _orderStatusId = OrderStatus.Shipped.Id; - _description = "The order was shipped."; - AddDomainEvent(new OrderShippedDomainEvent(this)); + StatusChangeException(OrderStatus.Shipped); } - public void SetCancelledStatus() - { - if (_orderStatusId == OrderStatus.Paid.Id || - _orderStatusId == OrderStatus.Shipped.Id) - { - StatusChangeException(OrderStatus.Cancelled); - } + _orderStatusId = OrderStatus.Shipped.Id; + _description = "The order was shipped."; + AddDomainEvent(new OrderShippedDomainEvent(this)); + } - _orderStatusId = OrderStatus.Cancelled.Id; - _description = $"The order was cancelled."; - AddDomainEvent(new OrderCancelledDomainEvent(this)); + public void SetCancelledStatus() + { + if (_orderStatusId == OrderStatus.Paid.Id || + _orderStatusId == OrderStatus.Shipped.Id) + { + StatusChangeException(OrderStatus.Cancelled); } - public void SetCancelledStatusWhenStockIsRejected(IEnumerable orderStockRejectedItems) + _orderStatusId = OrderStatus.Cancelled.Id; + _description = $"The order was cancelled."; + AddDomainEvent(new OrderCancelledDomainEvent(this)); + } + + public void SetCancelledStatusWhenStockIsRejected(IEnumerable orderStockRejectedItems) + { + if (_orderStatusId == OrderStatus.AwaitingValidation.Id) { - if (_orderStatusId == OrderStatus.AwaitingValidation.Id) - { - _orderStatusId = OrderStatus.Cancelled.Id; + _orderStatusId = OrderStatus.Cancelled.Id; - var itemsStockRejectedProductNames = OrderItems - .Where(c => orderStockRejectedItems.Contains(c.ProductId)) - .Select(c => c.GetOrderItemProductName()); + var itemsStockRejectedProductNames = OrderItems + .Where(c => orderStockRejectedItems.Contains(c.ProductId)) + .Select(c => c.GetOrderItemProductName()); - var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames); - _description = $"The product items don't have stock: ({itemsStockRejectedDescription})."; - } + var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames); + _description = $"The product items don't have stock: ({itemsStockRejectedDescription})."; } + } - private void AddOrderStartedDomainEvent(string userId, string userName, int cardTypeId, string cardNumber, - string cardSecurityNumber, string cardHolderName, DateTime cardExpiration) - { - var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, userName, cardTypeId, - cardNumber, cardSecurityNumber, - cardHolderName, cardExpiration); + private void AddOrderStartedDomainEvent(string userId, string userName, int cardTypeId, string cardNumber, + string cardSecurityNumber, string cardHolderName, DateTime cardExpiration) + { + var orderStartedDomainEvent = new OrderStartedDomainEvent(this, userId, userName, cardTypeId, + cardNumber, cardSecurityNumber, + cardHolderName, cardExpiration); - this.AddDomainEvent(orderStartedDomainEvent); - } + this.AddDomainEvent(orderStartedDomainEvent); + } - private void StatusChangeException(OrderStatus orderStatusToChange) - { - throw new OrderingDomainException($"Is not possible to change the order status from {OrderStatus.Name} to {orderStatusToChange.Name}."); - } + private void StatusChangeException(OrderStatus orderStatusToChange) + { + throw new OrderingDomainException($"Is not possible to change the order status from {OrderStatus.Name} to {orderStatusToChange.Name}."); + } - public decimal GetTotal() - { - return _orderItems.Sum(o => o.GetUnits() * o.GetUnitPrice()); - } + public decimal GetTotal() + { + return _orderItems.Sum(o => o.GetUnits() * o.GetUnitPrice()); } } - diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs index 9fbec8225..0b2d95002 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs @@ -1,82 +1,78 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using Ordering.Domain.Exceptions; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate +public class OrderItem + : Entity { - public class OrderItem - : Entity - { - // DDD Patterns comment - // Using private fields, allowed since EF Core 1.1, is a much better encapsulation - // aligned with DDD Aggregates and Domain Entities (Instead of properties and property collections) - private string _productName; - private string _pictureUrl; - private decimal _unitPrice; - private decimal _discount; - private int _units; + // DDD Patterns comment + // Using private fields, allowed since EF Core 1.1, is a much better encapsulation + // aligned with DDD Aggregates and Domain Entities (Instead of properties and property collections) + private string _productName; + private string _pictureUrl; + private decimal _unitPrice; + private decimal _discount; + private int _units; - public int ProductId { get; private set; } + public int ProductId { get; private set; } - protected OrderItem() { } + protected OrderItem() { } - public OrderItem(int productId, string productName, decimal unitPrice, decimal discount, string PictureUrl, int units = 1) + public OrderItem(int productId, string productName, decimal unitPrice, decimal discount, string PictureUrl, int units = 1) + { + if (units <= 0) { - if (units <= 0) - { - throw new OrderingDomainException("Invalid number of units"); - } - - if ((unitPrice * units) < discount) - { - throw new OrderingDomainException("The total of order item is lower than applied discount"); - } - - ProductId = productId; - - _productName = productName; - _unitPrice = unitPrice; - _discount = discount; - _units = units; - _pictureUrl = PictureUrl; + throw new OrderingDomainException("Invalid number of units"); } - public string GetPictureUri() => _pictureUrl; - - public decimal GetCurrentDiscount() + if ((unitPrice * units) < discount) { - return _discount; + throw new OrderingDomainException("The total of order item is lower than applied discount"); } - public int GetUnits() - { - return _units; - } + ProductId = productId; - public decimal GetUnitPrice() - { - return _unitPrice; - } + _productName = productName; + _unitPrice = unitPrice; + _discount = discount; + _units = units; + _pictureUrl = PictureUrl; + } - public string GetOrderItemProductName() => _productName; + public string GetPictureUri() => _pictureUrl; - public void SetNewDiscount(decimal discount) - { - if (discount < 0) - { - throw new OrderingDomainException("Discount is not valid"); - } + public decimal GetCurrentDiscount() + { + return _discount; + } - _discount = discount; - } + public int GetUnits() + { + return _units; + } + + public decimal GetUnitPrice() + { + return _unitPrice; + } + + public string GetOrderItemProductName() => _productName; - public void AddUnits(int units) + public void SetNewDiscount(decimal discount) + { + if (discount < 0) { - if (units < 0) - { - throw new OrderingDomainException("Invalid units"); - } + throw new OrderingDomainException("Discount is not valid"); + } + + _discount = discount; + } - _units += units; + public void AddUnits(int units) + { + if (units < 0) + { + throw new OrderingDomainException("Invalid units"); } + + _units += units; } } diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs index 19e62311a..aae09bc6a 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs @@ -1,52 +1,47 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate +using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; + +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + +public class OrderStatus + : Enumeration { - using global::Ordering.Domain.Exceptions; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; - using System; - using System.Collections.Generic; - using System.Linq; - - public class OrderStatus - : Enumeration + public static OrderStatus Submitted = new OrderStatus(1, nameof(Submitted).ToLowerInvariant()); + public static OrderStatus AwaitingValidation = new OrderStatus(2, nameof(AwaitingValidation).ToLowerInvariant()); + public static OrderStatus StockConfirmed = new OrderStatus(3, nameof(StockConfirmed).ToLowerInvariant()); + public static OrderStatus Paid = new OrderStatus(4, nameof(Paid).ToLowerInvariant()); + public static OrderStatus Shipped = new OrderStatus(5, nameof(Shipped).ToLowerInvariant()); + public static OrderStatus Cancelled = new OrderStatus(6, nameof(Cancelled).ToLowerInvariant()); + + public OrderStatus(int id, string name) + : base(id, name) { - public static OrderStatus Submitted = new OrderStatus(1, nameof(Submitted).ToLowerInvariant()); - public static OrderStatus AwaitingValidation = new OrderStatus(2, nameof(AwaitingValidation).ToLowerInvariant()); - public static OrderStatus StockConfirmed = new OrderStatus(3, nameof(StockConfirmed).ToLowerInvariant()); - public static OrderStatus Paid = new OrderStatus(4, nameof(Paid).ToLowerInvariant()); - public static OrderStatus Shipped = new OrderStatus(5, nameof(Shipped).ToLowerInvariant()); - public static OrderStatus Cancelled = new OrderStatus(6, nameof(Cancelled).ToLowerInvariant()); - - public OrderStatus(int id, string name) - : base(id, name) - { - } - - public static IEnumerable List() => - new[] { Submitted, AwaitingValidation, StockConfirmed, Paid, Shipped, Cancelled }; + } - public static OrderStatus FromName(string name) - { - var state = List() - .SingleOrDefault(s => String.Equals(s.Name, name, StringComparison.CurrentCultureIgnoreCase)); + public static IEnumerable List() => + new[] { Submitted, AwaitingValidation, StockConfirmed, Paid, Shipped, Cancelled }; - if (state == null) - { - throw new OrderingDomainException($"Possible values for OrderStatus: {String.Join(",", List().Select(s => s.Name))}"); - } + public static OrderStatus FromName(string name) + { + var state = List() + .SingleOrDefault(s => String.Equals(s.Name, name, StringComparison.CurrentCultureIgnoreCase)); - return state; + if (state == null) + { + throw new OrderingDomainException($"Possible values for OrderStatus: {String.Join(",", List().Select(s => s.Name))}"); } - public static OrderStatus From(int id) - { - var state = List().SingleOrDefault(s => s.Id == id); + return state; + } - if (state == null) - { - throw new OrderingDomainException($"Possible values for OrderStatus: {String.Join(",", List().Select(s => s.Name))}"); - } + public static OrderStatus From(int id) + { + var state = List().SingleOrDefault(s => s.Id == id); - return state; + if (state == null) + { + throw new OrderingDomainException($"Possible values for OrderStatus: {String.Join(",", List().Select(s => s.Name))}"); } + + return state; } } diff --git a/src/Services/Ordering/Ordering.Domain/Events/BuyerPaymentMethodVerifiedDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/BuyerPaymentMethodVerifiedDomainEvent.cs index 70adeefad..61acf898f 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/BuyerPaymentMethodVerifiedDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/BuyerPaymentMethodVerifiedDomainEvent.cs @@ -1,20 +1,16 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; -namespace Ordering.Domain.Events +public class BuyerAndPaymentMethodVerifiedDomainEvent + : INotification { - public class BuyerAndPaymentMethodVerifiedDomainEvent - : INotification - { - public Buyer Buyer { get; private set; } - public PaymentMethod Payment { get; private set; } - public int OrderId { get; private set; } + public Buyer Buyer { get; private set; } + public PaymentMethod Payment { get; private set; } + public int OrderId { get; private set; } - public BuyerAndPaymentMethodVerifiedDomainEvent(Buyer buyer, PaymentMethod payment, int orderId) - { - Buyer = buyer; - Payment = payment; - OrderId = orderId; - } + public BuyerAndPaymentMethodVerifiedDomainEvent(Buyer buyer, PaymentMethod payment, int orderId) + { + Buyer = buyer; + Payment = payment; + OrderId = orderId; } } diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderCancelledDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderCancelledDomainEvent.cs index 144527fbf..be0e34fe0 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/OrderCancelledDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderCancelledDomainEvent.cs @@ -1,15 +1,12 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; -namespace Ordering.Domain.Events +public class OrderCancelledDomainEvent : INotification { - public class OrderCancelledDomainEvent : INotification - { - public Order Order { get; } + public Order Order { get; } - public OrderCancelledDomainEvent(Order order) - { - Order = order; - } + public OrderCancelledDomainEvent(Order order) + { + Order = order; } } + diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderShippedDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderShippedDomainEvent.cs index 53fcef510..1b704ef77 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/OrderShippedDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderShippedDomainEvent.cs @@ -1,15 +1,11 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; -namespace Ordering.Domain.Events +public class OrderShippedDomainEvent : INotification { - public class OrderShippedDomainEvent : INotification - { - public Order Order { get; } + public Order Order { get; } - public OrderShippedDomainEvent(Order order) - { - Order = order; - } + public OrderShippedDomainEvent(Order order) + { + Order = order; } } diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderStartedDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderStartedDomainEvent.cs index ed779d4bc..8cc6a39e3 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/OrderStartedDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderStartedDomainEvent.cs @@ -1,8 +1,5 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using System; - -namespace Ordering.Domain.Events + +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events { /// /// Event used when an order is created diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToAwaitingValidationDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToAwaitingValidationDomainEvent.cs index b4dd7aa82..677ef321b 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToAwaitingValidationDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToAwaitingValidationDomainEvent.cs @@ -1,23 +1,18 @@ -namespace Ordering.Domain.Events +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; + +/// +/// Event used when the grace period order is confirmed +/// +public class OrderStatusChangedToAwaitingValidationDomainEvent + : INotification { - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - using System.Collections.Generic; + public int OrderId { get; } + public IEnumerable OrderItems { get; } - /// - /// Event used when the grace period order is confirmed - /// - public class OrderStatusChangedToAwaitingValidationDomainEvent - : INotification + public OrderStatusChangedToAwaitingValidationDomainEvent(int orderId, + IEnumerable orderItems) { - public int OrderId { get; } - public IEnumerable OrderItems { get; } - - public OrderStatusChangedToAwaitingValidationDomainEvent(int orderId, - IEnumerable orderItems) - { - OrderId = orderId; - OrderItems = orderItems; - } + OrderId = orderId; + OrderItems = orderItems; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToPaidDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToPaidDomainEvent.cs index f315bab60..0ef176564 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToPaidDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToPaidDomainEvent.cs @@ -1,23 +1,18 @@ -namespace Ordering.Domain.Events +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; + +/// +/// Event used when the order is paid +/// +public class OrderStatusChangedToPaidDomainEvent + : INotification { - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; - using System.Collections.Generic; + public int OrderId { get; } + public IEnumerable OrderItems { get; } - /// - /// Event used when the order is paid - /// - public class OrderStatusChangedToPaidDomainEvent - : INotification + public OrderStatusChangedToPaidDomainEvent(int orderId, + IEnumerable orderItems) { - public int OrderId { get; } - public IEnumerable OrderItems { get; } - - public OrderStatusChangedToPaidDomainEvent(int orderId, - IEnumerable orderItems) - { - OrderId = orderId; - OrderItems = orderItems; - } + OrderId = orderId; + OrderItems = orderItems; } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToStockConfirmedDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToStockConfirmedDomainEvent.cs index b16bebbcc..e897141ad 100644 --- a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToStockConfirmedDomainEvent.cs +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToStockConfirmedDomainEvent.cs @@ -1,16 +1,13 @@ -namespace Ordering.Domain.Events -{ - using MediatR; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; - /// - /// Event used when the order stock items are confirmed - /// - public class OrderStatusChangedToStockConfirmedDomainEvent - : INotification - { - public int OrderId { get; } +/// +/// Event used when the order stock items are confirmed +/// +public class OrderStatusChangedToStockConfirmedDomainEvent + : INotification +{ + public int OrderId { get; } - public OrderStatusChangedToStockConfirmedDomainEvent(int orderId) - => OrderId = orderId; - } -} \ No newline at end of file + public OrderStatusChangedToStockConfirmedDomainEvent(int orderId) + => OrderId = orderId; +} diff --git a/src/Services/Ordering/Ordering.Domain/Exceptions/OrderingDomainException.cs b/src/Services/Ordering/Ordering.Domain/Exceptions/OrderingDomainException.cs index 80c2262ca..fd31522fd 100644 --- a/src/Services/Ordering/Ordering.Domain/Exceptions/OrderingDomainException.cs +++ b/src/Services/Ordering/Ordering.Domain/Exceptions/OrderingDomainException.cs @@ -1,21 +1,18 @@ -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Exceptions; -namespace Ordering.Domain.Exceptions +/// +/// Exception type for domain exceptions +/// +public class OrderingDomainException : Exception { - /// - /// Exception type for domain exceptions - /// - public class OrderingDomainException : Exception - { - public OrderingDomainException() - { } + public OrderingDomainException() + { } - public OrderingDomainException(string message) - : base(message) - { } + public OrderingDomainException(string message) + : base(message) + { } - public OrderingDomainException(string message, Exception innerException) - : base(message, innerException) - { } - } + public OrderingDomainException(string message, Exception innerException) + : base(message, innerException) + { } } diff --git a/src/Services/Ordering/Ordering.Domain/GlobalUsings.cs b/src/Services/Ordering/Ordering.Domain/GlobalUsings.cs new file mode 100644 index 000000000..bc11cd71b --- /dev/null +++ b/src/Services/Ordering/Ordering.Domain/GlobalUsings.cs @@ -0,0 +1,13 @@ +global using global::Microsoft.eShopOnContainers.Services.Ordering.Domain.Exceptions; +global using MediatR; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Exceptions; +global using System.Collections.Generic; +global using System.Linq; +global using System.Reflection; +global using System.Threading.Tasks; +global using System.Threading; +global using System; \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj b/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj index ce9c519ae..7ca0dc00f 100644 --- a/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj +++ b/src/Services/Ordering/Ordering.Domain/Ordering.Domain.csproj @@ -1,12 +1,12 @@  - net5.0 + net6.0 - - + + diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/Entity.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/Entity.cs index f58df286b..a8e5c23ad 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/Entity.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/Entity.cs @@ -1,92 +1,87 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork -{ - using MediatR; - using System; - using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; - public abstract class Entity +public abstract class Entity +{ + int? _requestedHashCode; + int _Id; + public virtual int Id { - int? _requestedHashCode; - int _Id; - public virtual int Id + get { - get - { - return _Id; - } - protected set - { - _Id = value; - } + return _Id; } - - private List _domainEvents; - public IReadOnlyCollection DomainEvents => _domainEvents?.AsReadOnly(); - - public void AddDomainEvent(INotification eventItem) + protected set { - _domainEvents = _domainEvents ?? new List(); - _domainEvents.Add(eventItem); + _Id = value; } + } - public void RemoveDomainEvent(INotification eventItem) - { - _domainEvents?.Remove(eventItem); - } + private List _domainEvents; + public IReadOnlyCollection DomainEvents => _domainEvents?.AsReadOnly(); - public void ClearDomainEvents() - { - _domainEvents?.Clear(); - } + public void AddDomainEvent(INotification eventItem) + { + _domainEvents = _domainEvents ?? new List(); + _domainEvents.Add(eventItem); + } - public bool IsTransient() - { - return this.Id == default(Int32); - } + public void RemoveDomainEvent(INotification eventItem) + { + _domainEvents?.Remove(eventItem); + } - public override bool Equals(object obj) - { - if (obj == null || !(obj is Entity)) - return false; + public void ClearDomainEvents() + { + _domainEvents?.Clear(); + } - if (Object.ReferenceEquals(this, obj)) - return true; + public bool IsTransient() + { + return this.Id == default(Int32); + } - if (this.GetType() != obj.GetType()) - return false; + public override bool Equals(object obj) + { + if (obj == null || !(obj is Entity)) + return false; - Entity item = (Entity)obj; + if (Object.ReferenceEquals(this, obj)) + return true; - if (item.IsTransient() || this.IsTransient()) - return false; - else - return item.Id == this.Id; - } + if (this.GetType() != obj.GetType()) + return false; - public override int GetHashCode() - { - if (!IsTransient()) - { - if (!_requestedHashCode.HasValue) - _requestedHashCode = this.Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx) + Entity item = (Entity)obj; - return _requestedHashCode.Value; - } - else - return base.GetHashCode(); + if (item.IsTransient() || this.IsTransient()) + return false; + else + return item.Id == this.Id; + } - } - public static bool operator ==(Entity left, Entity right) + public override int GetHashCode() + { + if (!IsTransient()) { - if (Object.Equals(left, null)) - return (Object.Equals(right, null)) ? true : false; - else - return left.Equals(right); - } + if (!_requestedHashCode.HasValue) + _requestedHashCode = this.Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx) - public static bool operator !=(Entity left, Entity right) - { - return !(left == right); + return _requestedHashCode.Value; } + else + return base.GetHashCode(); + + } + public static bool operator ==(Entity left, Entity right) + { + if (Object.Equals(left, null)) + return (Object.Equals(right, null)) ? true : false; + else + return left.Equals(right); + } + + public static bool operator !=(Entity left, Entity right) + { + return !(left == right); } } diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs index d3e415df2..8d313149d 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/Enumeration.cs @@ -1,74 +1,64 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork +public abstract class Enumeration : IComparable { - public abstract class Enumeration : IComparable + public string Name { get; private set; } + + public int Id { get; private set; } + + protected Enumeration(int id, string name) => (Id, Name) = (id, name); + + public override string ToString() => Name; + + public static IEnumerable GetAll() where T : Enumeration => + typeof(T).GetFields(BindingFlags.Public | + BindingFlags.Static | + BindingFlags.DeclaredOnly) + .Select(f => f.GetValue(null)) + .Cast(); + + public override bool Equals(object obj) { - public string Name { get; private set; } - - public int Id { get; private set; } - - protected Enumeration(int id, string name) - { - Id = id; - Name = name; - } - - public override string ToString() => Name; - - public static IEnumerable GetAll() where T : Enumeration + if (obj is not Enumeration otherValue) { - var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); - - return fields.Select(f => f.GetValue(null)).Cast(); + return false; } - public override bool Equals(object obj) - { - var otherValue = obj as Enumeration; + var typeMatches = GetType().Equals(obj.GetType()); + var valueMatches = Id.Equals(otherValue.Id); - if (otherValue == null) - return false; - - var typeMatches = GetType().Equals(obj.GetType()); - var valueMatches = Id.Equals(otherValue.Id); - - return typeMatches && valueMatches; - } - - public override int GetHashCode() => Id.GetHashCode(); + return typeMatches && valueMatches; + } - public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue) - { - var absoluteDifference = Math.Abs(firstValue.Id - secondValue.Id); - return absoluteDifference; - } + public override int GetHashCode() => Id.GetHashCode(); - public static T FromValue(int value) where T : Enumeration - { - var matchingItem = Parse(value, "value", item => item.Id == value); - return matchingItem; - } + public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue) + { + var absoluteDifference = Math.Abs(firstValue.Id - secondValue.Id); + return absoluteDifference; + } - public static T FromDisplayName(string displayName) where T : Enumeration - { - var matchingItem = Parse(displayName, "display name", item => item.Name == displayName); - return matchingItem; - } + public static T FromValue(int value) where T : Enumeration + { + var matchingItem = Parse(value, "value", item => item.Id == value); + return matchingItem; + } - private static T Parse(K value, string description, Func predicate) where T : Enumeration - { - var matchingItem = GetAll().FirstOrDefault(predicate); + public static T FromDisplayName(string displayName) where T : Enumeration + { + var matchingItem = Parse(displayName, "display name", item => item.Name == displayName); + return matchingItem; + } - if (matchingItem == null) - throw new InvalidOperationException($"'{value}' is not a valid {description} in {typeof(T)}"); + private static T Parse(K value, string description, Func predicate) where T : Enumeration + { + var matchingItem = GetAll().FirstOrDefault(predicate); - return matchingItem; - } + if (matchingItem == null) + throw new InvalidOperationException($"'{value}' is not a valid {description} in {typeof(T)}"); - public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id); + return matchingItem; } + + public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id); } diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/IAggregateRoot.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/IAggregateRoot.cs index 47a8dc7b5..9af3a0437 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/IAggregateRoot.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/IAggregateRoot.cs @@ -1,6 +1,5 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork -{ +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; + +public interface IAggregateRoot { } - public interface IAggregateRoot { } -} diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/IRepository.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/IRepository.cs index 3657ec092..f9b84a7f0 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/IRepository.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/IRepository.cs @@ -1,7 +1,6 @@ -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; + +public interface IRepository where T : IAggregateRoot { - public interface IRepository where T : IAggregateRoot - { - IUnitOfWork UnitOfWork { get; } - } + IUnitOfWork UnitOfWork { get; } } diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs index a6cfca7c6..b9c121655 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/IUnitOfWork.cs @@ -1,12 +1,7 @@ -using System; -using System.Threading; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork +public interface IUnitOfWork : IDisposable { - public interface IUnitOfWork : IDisposable - { - Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); - Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)); - } + Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); + Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)); } diff --git a/src/Services/Ordering/Ordering.Domain/SeedWork/ValueObject.cs b/src/Services/Ordering/Ordering.Domain/SeedWork/ValueObject.cs index 5f36900ee..8111088f8 100644 --- a/src/Services/Ordering/Ordering.Domain/SeedWork/ValueObject.cs +++ b/src/Services/Ordering/Ordering.Domain/SeedWork/ValueObject.cs @@ -1,48 +1,44 @@ -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; -namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork +public abstract class ValueObject { - public abstract class ValueObject + protected static bool EqualOperator(ValueObject left, ValueObject right) { - protected static bool EqualOperator(ValueObject left, ValueObject right) + if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null)) { - if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null)) - { - return false; - } - return ReferenceEquals(left, null) || left.Equals(right); + return false; } + return ReferenceEquals(left, null) || left.Equals(right); + } - protected static bool NotEqualOperator(ValueObject left, ValueObject right) - { - return !(EqualOperator(left, right)); - } + protected static bool NotEqualOperator(ValueObject left, ValueObject right) + { + return !(EqualOperator(left, right)); + } - protected abstract IEnumerable GetEqualityComponents(); + protected abstract IEnumerable GetEqualityComponents(); - public override bool Equals(object obj) + public override bool Equals(object obj) + { + if (obj == null || obj.GetType() != GetType()) { - if (obj == null || obj.GetType() != GetType()) - { - return false; - } + return false; + } - var other = (ValueObject)obj; + var other = (ValueObject)obj; - return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); - } + return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); + } - public override int GetHashCode() - { - return GetEqualityComponents() - .Select(x => x != null ? x.GetHashCode() : 0) - .Aggregate((x, y) => x ^ y); - } + public override int GetHashCode() + { + return GetEqualityComponents() + .Select(x => x != null ? x.GetHashCode() : 0) + .Aggregate((x, y) => x ^ y); + } - public ValueObject GetCopy() - { - return this.MemberwiseClone() as ValueObject; - } + public ValueObject GetCopy() + { + return this.MemberwiseClone() as ValueObject; } } diff --git a/src/Services/Ordering/Ordering.FunctionalTests/AutoAuthorizeMiddleware.cs b/src/Services/Ordering/Ordering.FunctionalTests/AutoAuthorizeMiddleware.cs index a1f77b75d..8062dd5d0 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/AutoAuthorizeMiddleware.cs +++ b/src/Services/Ordering/Ordering.FunctionalTests/AutoAuthorizeMiddleware.cs @@ -1,31 +1,26 @@ -using Microsoft.AspNetCore.Http; -using System.Security.Claims; -using System.Threading.Tasks; +namespace Ordering.FunctionalTests; -namespace Ordering.FunctionalTests +class AutoAuthorizeMiddleware { - class AutoAuthorizeMiddleware - { - public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"; + public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"; - private readonly RequestDelegate _next; + private readonly RequestDelegate _next; - public AutoAuthorizeMiddleware(RequestDelegate rd) - { - _next = rd; - } + public AutoAuthorizeMiddleware(RequestDelegate rd) + { + _next = rd; + } - public async Task Invoke(HttpContext httpContext) - { - var identity = new ClaimsIdentity("cookies"); + public async Task Invoke(HttpContext httpContext) + { + var identity = new ClaimsIdentity("cookies"); - identity.AddClaim(new Claim("sub", IDENTITY_ID)); - identity.AddClaim(new Claim("unique_name", IDENTITY_ID)); - identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID)); + identity.AddClaim(new Claim("sub", IDENTITY_ID)); + identity.AddClaim(new Claim("unique_name", IDENTITY_ID)); + identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID)); - httpContext.User.AddIdentity(identity); + httpContext.User.AddIdentity(identity); - await _next.Invoke(httpContext); - } + await _next.Invoke(httpContext); } } diff --git a/src/Services/Ordering/Ordering.FunctionalTests/GlobalUsings.cs b/src/Services/Ordering/Ordering.FunctionalTests/GlobalUsings.cs new file mode 100644 index 000000000..cee4b6733 --- /dev/null +++ b/src/Services/Ordering/Ordering.FunctionalTests/GlobalUsings.cs @@ -0,0 +1,19 @@ +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Routing; +global using Microsoft.AspNetCore.TestHost; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; +global using Microsoft.eShopOnContainers.Services.Ordering.API; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using System.IO; +global using System.Net.Http; +global using System.Reflection; +global using System.Security.Claims; +global using System.Threading.Tasks; +global using System; diff --git a/src/Services/Ordering/Ordering.FunctionalTests/HttpClientExtensions.cs b/src/Services/Ordering/Ordering.FunctionalTests/HttpClientExtensions.cs index da2577b24..a4a0dd9c2 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/HttpClientExtensions.cs +++ b/src/Services/Ordering/Ordering.FunctionalTests/HttpClientExtensions.cs @@ -1,16 +1,11 @@ -using Microsoft.AspNetCore.TestHost; -using System; -using System.Net.Http; +namespace Ordering.FunctionalTests; -namespace Ordering.FunctionalTests +static class HttpClientExtensions { - static class HttpClientExtensions + public static HttpClient CreateIdempotentClient(this TestServer server) { - public static HttpClient CreateIdempotentClient(this TestServer server) - { - var client = server.CreateClient(); - client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); - return client; - } + var client = server.CreateClient(); + client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); + return client; } } diff --git a/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj b/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj index 7d835c981..b55420205 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj +++ b/src/Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 false @@ -17,9 +17,9 @@ - + - + all runtime; build; native; contentfiles; analyzers diff --git a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarioBase.cs b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarioBase.cs index 962ce21c1..d03d54380 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarioBase.cs +++ b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarioBase.cs @@ -1,65 +1,51 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.Services.Ordering.API; -using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.IO; -using System.Reflection; +namespace Ordering.FunctionalTests; -namespace Ordering.FunctionalTests +public class OrderingScenarioBase { - public class OrderingScenarioBase + public TestServer CreateServer() { - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(OrderingScenarioBase)) - .Location; + var path = Assembly.GetAssembly(typeof(OrderingScenarioBase)) + .Location; - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("appsettings.json", optional: false) - .AddEnvironmentVariables(); - }).UseStartup(); + var hostBuilder = new WebHostBuilder() + .UseContentRoot(Path.GetDirectoryName(path)) + .ConfigureAppConfiguration(cb => + { + cb.AddJsonFile("appsettings.json", optional: false) + .AddEnvironmentVariables(); + }).UseStartup(); - var testServer = new TestServer(hostBuilder); + var testServer = new TestServer(hostBuilder); - testServer.Host - .MigrateDbContext((context, services) => - { - var env = services.GetService(); - var settings = services.GetService>(); - var logger = services.GetService>(); + testServer.Host + .MigrateDbContext((context, services) => + { + var env = services.GetService(); + var settings = services.GetService>(); + var logger = services.GetService>(); - new OrderingContextSeed() - .SeedAsync(context, env, settings, logger) - .Wait(); - }) - .MigrateDbContext((_, __) => { }); + new OrderingContextSeed() + .SeedAsync(context, env, settings, logger) + .Wait(); + }) + .MigrateDbContext((_, __) => { }); - return testServer; - } - - public static class Get - { - public static string Orders = "api/v1/orders"; + return testServer; + } - public static string OrderBy(int id) - { - return $"api/v1/orders/{id}"; - } - } + public static class Get + { + public static string Orders = "api/v1/orders"; - public static class Put + public static string OrderBy(int id) { - public static string CancelOrder = "api/v1/orders/cancel"; - public static string ShipOrder = "api/v1/orders/ship"; + return $"api/v1/orders/{id}"; } } + + public static class Put + { + public static string CancelOrder = "api/v1/orders/cancel"; + public static string ShipOrder = "api/v1/orders/ship"; + } } diff --git a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs index 9b46e1841..d49f41960 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs +++ b/src/Services/Ordering/Ordering.FunctionalTests/OrderingScenarios.cs @@ -1,7 +1,7 @@ -using Newtonsoft.Json; -using System.Net; +using System.Net; using System.Net.Http; using System.Text; +using System.Text.Json; using System.Threading.Tasks; using WebMVC.Services.ModelDTOs; using Xunit; @@ -14,39 +14,33 @@ namespace Ordering.FunctionalTests [Fact] public async Task Get_get_all_stored_orders_and_response_ok_status_code() { - using (var server = CreateServer()) - { - var response = await server.CreateClient() - .GetAsync(Get.Orders); + using var server = CreateServer(); + var response = await server.CreateClient() + .GetAsync(Get.Orders); - response.EnsureSuccessStatusCode(); - } + response.EnsureSuccessStatusCode(); } [Fact] public async Task Cancel_order_no_order_created_bad_request_response() { - using (var server = CreateServer()) - { - var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateIdempotentClient() - .PutAsync(Put.CancelOrder, content); + using var server = CreateServer(); + var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PutAsync(Put.CancelOrder, content); - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } [Fact] public async Task Ship_order_no_order_created_bad_request_response() { - using (var server = CreateServer()) - { - var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); - var response = await server.CreateIdempotentClient() - .PutAsync(Put.ShipOrder, content); + using var server = CreateServer(); + var content = new StringContent(BuildOrder(), UTF8Encoding.UTF8, "application/json"); + var response = await server.CreateIdempotentClient() + .PutAsync(Put.ShipOrder, content); - Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); - } + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } string BuildOrder() @@ -55,7 +49,7 @@ namespace Ordering.FunctionalTests { OrderNumber = "-1" }; - return JsonConvert.SerializeObject(order); + return JsonSerializer.Serialize(order); } } } diff --git a/src/Services/Ordering/Ordering.FunctionalTests/OrderingTestStartup.cs b/src/Services/Ordering/Ordering.FunctionalTests/OrderingTestStartup.cs index 7980d5bff..7367042de 100644 --- a/src/Services/Ordering/Ordering.FunctionalTests/OrderingTestStartup.cs +++ b/src/Services/Ordering/Ordering.FunctionalTests/OrderingTestStartup.cs @@ -1,35 +1,27 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Routing; -using Microsoft.eShopOnContainers.Services.Ordering.API; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using System; +namespace Ordering.FunctionalTests; -namespace Ordering.FunctionalTests +public class OrderingTestsStartup : Startup { - public class OrderingTestsStartup : Startup + public OrderingTestsStartup(IConfiguration env) : base(env) { - public OrderingTestsStartup(IConfiguration env) : base(env) - { - } + } - public override IServiceProvider ConfigureServices(IServiceCollection services) + public override IServiceProvider ConfigureServices(IServiceCollection services) + { + // Added to avoid the Authorize data annotation in test environment. + // Property "SuppressCheckForUnhandledSecurityMetadata" in appsettings.json + services.Configure(Configuration); + return base.ConfigureServices(services); + } + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) { - // Added to avoid the Authorize data annotation in test environment. - // Property "SuppressCheckForUnhandledSecurityMetadata" in appsettings.json - services.Configure(Configuration); - return base.ConfigureServices(services); + app.UseMiddleware(); } - protected override void ConfigureAuth(IApplicationBuilder app) + else { - if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) - { - app.UseMiddleware(); - } - else - { - base.ConfigureAuth(app); - } + base.ConfigureAuth(app); } } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTypeConfiguration.cs index f5bdea756..06ea7bcf6 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/BuyerEntityTypeConfiguration.cs @@ -1,41 +1,35 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class BuyerEntityTypeConfiguration + : IEntityTypeConfiguration { - class BuyerEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder buyerConfiguration) { - public void Configure(EntityTypeBuilder buyerConfiguration) - { - buyerConfiguration.ToTable("buyers", OrderingContext.DEFAULT_SCHEMA); + buyerConfiguration.ToTable("buyers", OrderingContext.DEFAULT_SCHEMA); - buyerConfiguration.HasKey(b => b.Id); + buyerConfiguration.HasKey(b => b.Id); - buyerConfiguration.Ignore(b => b.DomainEvents); + buyerConfiguration.Ignore(b => b.DomainEvents); - buyerConfiguration.Property(b => b.Id) - .UseHiLo("buyerseq", OrderingContext.DEFAULT_SCHEMA); + buyerConfiguration.Property(b => b.Id) + .UseHiLo("buyerseq", OrderingContext.DEFAULT_SCHEMA); - buyerConfiguration.Property(b => b.IdentityGuid) - .HasMaxLength(200) - .IsRequired(); + buyerConfiguration.Property(b => b.IdentityGuid) + .HasMaxLength(200) + .IsRequired(); - buyerConfiguration.HasIndex("IdentityGuid") - .IsUnique(true); + buyerConfiguration.HasIndex("IdentityGuid") + .IsUnique(true); - buyerConfiguration.Property(b => b.Name); + buyerConfiguration.Property(b => b.Name); - buyerConfiguration.HasMany(b => b.PaymentMethods) - .WithOne() - .HasForeignKey("BuyerId") - .OnDelete(DeleteBehavior.Cascade); + buyerConfiguration.HasMany(b => b.PaymentMethods) + .WithOne() + .HasForeignKey("BuyerId") + .OnDelete(DeleteBehavior.Cascade); - var navigation = buyerConfiguration.Metadata.FindNavigation(nameof(Buyer.PaymentMethods)); + var navigation = buyerConfiguration.Metadata.FindNavigation(nameof(Buyer.PaymentMethods)); - navigation.SetPropertyAccessMode(PropertyAccessMode.Field); - } + navigation.SetPropertyAccessMode(PropertyAccessMode.Field); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/CardTypeEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/CardTypeEntityTypeConfiguration.cs index cdac780a1..c305c045b 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/CardTypeEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/CardTypeEntityTypeConfiguration.cs @@ -1,27 +1,21 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class CardTypeEntityTypeConfiguration + : IEntityTypeConfiguration { - class CardTypeEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder cardTypesConfiguration) { - public void Configure(EntityTypeBuilder cardTypesConfiguration) - { - cardTypesConfiguration.ToTable("cardtypes", OrderingContext.DEFAULT_SCHEMA); + cardTypesConfiguration.ToTable("cardtypes", OrderingContext.DEFAULT_SCHEMA); - cardTypesConfiguration.HasKey(ct => ct.Id); + cardTypesConfiguration.HasKey(ct => ct.Id); - cardTypesConfiguration.Property(ct => ct.Id) - .HasDefaultValue(1) - .ValueGeneratedNever() - .IsRequired(); + cardTypesConfiguration.Property(ct => ct.Id) + .HasDefaultValue(1) + .ValueGeneratedNever() + .IsRequired(); - cardTypesConfiguration.Property(ct => ct.Name) - .HasMaxLength(200) - .IsRequired(); - } + cardTypesConfiguration.Property(ct => ct.Name) + .HasMaxLength(200) + .IsRequired(); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/ClientRequestEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/ClientRequestEntityTypeConfiguration.cs index 5a5f8547e..17ee92e02 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/ClientRequestEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/ClientRequestEntityTypeConfiguration.cs @@ -1,19 +1,13 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class ClientRequestEntityTypeConfiguration + : IEntityTypeConfiguration { - class ClientRequestEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder requestConfiguration) { - public void Configure(EntityTypeBuilder requestConfiguration) - { - requestConfiguration.ToTable("requests", OrderingContext.DEFAULT_SCHEMA); - requestConfiguration.HasKey(cr => cr.Id); - requestConfiguration.Property(cr => cr.Name).IsRequired(); - requestConfiguration.Property(cr => cr.Time).IsRequired(); - } + requestConfiguration.ToTable("requests", OrderingContext.DEFAULT_SCHEMA); + requestConfiguration.HasKey(cr => cr.Id); + requestConfiguration.Property(cr => cr.Name).IsRequired(); + requestConfiguration.Property(cr => cr.Time).IsRequired(); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderEntityTypeConfiguration.cs index 4e32763eb..e8fe7d97b 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderEntityTypeConfiguration.cs @@ -1,86 +1,78 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class OrderEntityTypeConfiguration : IEntityTypeConfiguration { - class OrderEntityTypeConfiguration : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder orderConfiguration) { - public void Configure(EntityTypeBuilder orderConfiguration) - { - orderConfiguration.ToTable("orders", OrderingContext.DEFAULT_SCHEMA); + orderConfiguration.ToTable("orders", OrderingContext.DEFAULT_SCHEMA); - orderConfiguration.HasKey(o => o.Id); + orderConfiguration.HasKey(o => o.Id); - orderConfiguration.Ignore(b => b.DomainEvents); + orderConfiguration.Ignore(b => b.DomainEvents); - orderConfiguration.Property(o => o.Id) - .UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); + orderConfiguration.Property(o => o.Id) + .UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); - //Address value object persisted as owned entity type supported since EF Core 2.0 - orderConfiguration - .OwnsOne(o => o.Address, a => - { - // Explicit configuration of the shadow key property in the owned type - // as a workaround for a documented issue in EF Core 5: https://github.com/dotnet/efcore/issues/20740 - a.Property("OrderId") - .UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); - a.WithOwner(); - }); + //Address value object persisted as owned entity type supported since EF Core 2.0 + orderConfiguration + .OwnsOne(o => o.Address, a => + { + // Explicit configuration of the shadow key property in the owned type + // as a workaround for a documented issue in EF Core 5: https://github.com/dotnet/efcore/issues/20740 + a.Property("OrderId") + .UseHiLo("orderseq", OrderingContext.DEFAULT_SCHEMA); + a.WithOwner(); + }); - orderConfiguration - .Property("_buyerId") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("BuyerId") - .IsRequired(false); + orderConfiguration + .Property("_buyerId") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("BuyerId") + .IsRequired(false); - orderConfiguration - .Property("_orderDate") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("OrderDate") - .IsRequired(); + orderConfiguration + .Property("_orderDate") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("OrderDate") + .IsRequired(); - orderConfiguration - .Property("_orderStatusId") - // .HasField("_orderStatusId") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("OrderStatusId") - .IsRequired(); + orderConfiguration + .Property("_orderStatusId") + // .HasField("_orderStatusId") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("OrderStatusId") + .IsRequired(); - orderConfiguration - .Property("_paymentMethodId") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("PaymentMethodId") - .IsRequired(false); + orderConfiguration + .Property("_paymentMethodId") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("PaymentMethodId") + .IsRequired(false); - orderConfiguration.Property("Description").IsRequired(false); + orderConfiguration.Property("Description").IsRequired(false); - var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems)); + var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems)); - // DDD Patterns comment: - //Set as field (New since EF 1.1) to access the OrderItem collection property through its field - navigation.SetPropertyAccessMode(PropertyAccessMode.Field); + // DDD Patterns comment: + //Set as field (New since EF 1.1) to access the OrderItem collection property through its field + navigation.SetPropertyAccessMode(PropertyAccessMode.Field); - orderConfiguration.HasOne() - .WithMany() - // .HasForeignKey("PaymentMethodId") - .HasForeignKey("_paymentMethodId") - .IsRequired(false) - .OnDelete(DeleteBehavior.Restrict); + orderConfiguration.HasOne() + .WithMany() + // .HasForeignKey("PaymentMethodId") + .HasForeignKey("_paymentMethodId") + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); - orderConfiguration.HasOne() - .WithMany() - .IsRequired(false) - // .HasForeignKey("BuyerId"); - .HasForeignKey("_buyerId"); + orderConfiguration.HasOne() + .WithMany() + .IsRequired(false) + // .HasForeignKey("BuyerId"); + .HasForeignKey("_buyerId"); - orderConfiguration.HasOne(o => o.OrderStatus) - .WithMany() - // .HasForeignKey("OrderStatusId"); - .HasForeignKey("_orderStatusId"); - } + orderConfiguration.HasOne(o => o.OrderStatus) + .WithMany() + // .HasForeignKey("OrderStatusId"); + .HasForeignKey("_orderStatusId"); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderItemEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderItemEntityTypeConfiguration.cs index 9fd5734ed..04e2bbec5 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderItemEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderItemEntityTypeConfiguration.cs @@ -1,59 +1,53 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class OrderItemEntityTypeConfiguration + : IEntityTypeConfiguration { - class OrderItemEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder orderItemConfiguration) { - public void Configure(EntityTypeBuilder orderItemConfiguration) - { - orderItemConfiguration.ToTable("orderItems", OrderingContext.DEFAULT_SCHEMA); - - orderItemConfiguration.HasKey(o => o.Id); - - orderItemConfiguration.Ignore(b => b.DomainEvents); - - orderItemConfiguration.Property(o => o.Id) - .UseHiLo("orderitemseq"); - - orderItemConfiguration.Property("OrderId") - .IsRequired(); - - orderItemConfiguration - .Property("_discount") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("Discount") - .IsRequired(); - - orderItemConfiguration.Property("ProductId") - .IsRequired(); - - orderItemConfiguration - .Property("_productName") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("ProductName") - .IsRequired(); - - orderItemConfiguration - .Property("_unitPrice") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("UnitPrice") - .IsRequired(); - - orderItemConfiguration - .Property("_units") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("Units") - .IsRequired(); - - orderItemConfiguration - .Property("_pictureUrl") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("PictureUrl") - .IsRequired(false); - } + orderItemConfiguration.ToTable("orderItems", OrderingContext.DEFAULT_SCHEMA); + + orderItemConfiguration.HasKey(o => o.Id); + + orderItemConfiguration.Ignore(b => b.DomainEvents); + + orderItemConfiguration.Property(o => o.Id) + .UseHiLo("orderitemseq"); + + orderItemConfiguration.Property("OrderId") + .IsRequired(); + + orderItemConfiguration + .Property("_discount") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("Discount") + .IsRequired(); + + orderItemConfiguration.Property("ProductId") + .IsRequired(); + + orderItemConfiguration + .Property("_productName") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("ProductName") + .IsRequired(); + + orderItemConfiguration + .Property("_unitPrice") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("UnitPrice") + .IsRequired(); + + orderItemConfiguration + .Property("_units") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("Units") + .IsRequired(); + + orderItemConfiguration + .Property("_pictureUrl") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("PictureUrl") + .IsRequired(false); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderStatusEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderStatusEntityTypeConfiguration.cs index f968d9011..c99eb6bbe 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderStatusEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/OrderStatusEntityTypeConfiguration.cs @@ -1,27 +1,21 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class OrderStatusEntityTypeConfiguration + : IEntityTypeConfiguration { - class OrderStatusEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder orderStatusConfiguration) { - public void Configure(EntityTypeBuilder orderStatusConfiguration) - { - orderStatusConfiguration.ToTable("orderstatus", OrderingContext.DEFAULT_SCHEMA); + orderStatusConfiguration.ToTable("orderstatus", OrderingContext.DEFAULT_SCHEMA); - orderStatusConfiguration.HasKey(o => o.Id); + orderStatusConfiguration.HasKey(o => o.Id); - orderStatusConfiguration.Property(o => o.Id) - .HasDefaultValue(1) - .ValueGeneratedNever() - .IsRequired(); + orderStatusConfiguration.Property(o => o.Id) + .HasDefaultValue(1) + .ValueGeneratedNever() + .IsRequired(); - orderStatusConfiguration.Property(o => o.Name) - .HasMaxLength(200) - .IsRequired(); - } + orderStatusConfiguration.Property(o => o.Name) + .HasMaxLength(200) + .IsRequired(); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/PaymentMethodEntityTypeConfiguration.cs b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/PaymentMethodEntityTypeConfiguration.cs index 52fdf5f24..9083bcfcb 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/PaymentMethodEntityTypeConfiguration.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/EntityConfigurations/PaymentMethodEntityTypeConfiguration.cs @@ -1,65 +1,58 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; -namespace Ordering.Infrastructure.EntityConfigurations +class PaymentMethodEntityTypeConfiguration + : IEntityTypeConfiguration { - class PaymentMethodEntityTypeConfiguration - : IEntityTypeConfiguration + public void Configure(EntityTypeBuilder paymentConfiguration) { - public void Configure(EntityTypeBuilder paymentConfiguration) - { - paymentConfiguration.ToTable("paymentmethods", OrderingContext.DEFAULT_SCHEMA); - - paymentConfiguration.HasKey(b => b.Id); - - paymentConfiguration.Ignore(b => b.DomainEvents); - - paymentConfiguration.Property(b => b.Id) - .UseHiLo("paymentseq", OrderingContext.DEFAULT_SCHEMA); - - paymentConfiguration.Property("BuyerId") - .IsRequired(); - - paymentConfiguration - .Property("_cardHolderName") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("CardHolderName") - .HasMaxLength(200) - .IsRequired(); - - paymentConfiguration - .Property("_alias") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("Alias") - .HasMaxLength(200) - .IsRequired(); - - paymentConfiguration - .Property("_cardNumber") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("CardNumber") - .HasMaxLength(25) - .IsRequired(); - - paymentConfiguration - .Property("_expiration") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("Expiration") - .HasMaxLength(25) - .IsRequired(); - - paymentConfiguration - .Property("_cardTypeId") - .UsePropertyAccessMode(PropertyAccessMode.Field) - .HasColumnName("CardTypeId") - .IsRequired(); - - paymentConfiguration.HasOne(p => p.CardType) - .WithMany() - .HasForeignKey("_cardTypeId"); - } + paymentConfiguration.ToTable("paymentmethods", OrderingContext.DEFAULT_SCHEMA); + + paymentConfiguration.HasKey(b => b.Id); + + paymentConfiguration.Ignore(b => b.DomainEvents); + + paymentConfiguration.Property(b => b.Id) + .UseHiLo("paymentseq", OrderingContext.DEFAULT_SCHEMA); + + paymentConfiguration.Property("BuyerId") + .IsRequired(); + + paymentConfiguration + .Property("_cardHolderName") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("CardHolderName") + .HasMaxLength(200) + .IsRequired(); + + paymentConfiguration + .Property("_alias") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("Alias") + .HasMaxLength(200) + .IsRequired(); + + paymentConfiguration + .Property("_cardNumber") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("CardNumber") + .HasMaxLength(25) + .IsRequired(); + + paymentConfiguration + .Property("_expiration") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("Expiration") + .HasMaxLength(25) + .IsRequired(); + + paymentConfiguration + .Property("_cardTypeId") + .UsePropertyAccessMode(PropertyAccessMode.Field) + .HasColumnName("CardTypeId") + .IsRequired(); + + paymentConfiguration.HasOne(p => p.CardType) + .WithMany() + .HasForeignKey("_cardTypeId"); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/GlobalUsings.cs b/src/Services/Ordering/Ordering.Infrastructure/GlobalUsings.cs new file mode 100644 index 000000000..72667e11d --- /dev/null +++ b/src/Services/Ordering/Ordering.Infrastructure/GlobalUsings.cs @@ -0,0 +1,18 @@ +global using MediatR; +global using Microsoft.EntityFrameworkCore.Design; +global using Microsoft.EntityFrameworkCore.Metadata.Builders; +global using Microsoft.EntityFrameworkCore.Storage; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Exceptions; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.EntityConfigurations; +global using System.Data; +global using System.Linq; +global using System.Threading.Tasks; +global using System.Threading; +global using System; +global using System.Collections.Generic; \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs index 7ca49fa41..96002ce1b 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/ClientRequest.cs @@ -1,11 +1,8 @@ -using System; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency +public class ClientRequest { - public class ClientRequest - { - public Guid Id { get; set; } - public string Name { get; set; } - public DateTime Time { get; set; } - } + public Guid Id { get; set; } + public string Name { get; set; } + public DateTime Time { get; set; } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs index d38c23e09..7adb31fe2 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/IRequestManager.cs @@ -1,12 +1,8 @@ -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency +public interface IRequestManager { - public interface IRequestManager - { - Task ExistAsync(Guid id); + Task ExistAsync(Guid id); - Task CreateRequestForCommandAsync(Guid id); - } + Task CreateRequestForCommandAsync(Guid id); } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs index f2ae2d876..bb053eeaf 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Idempotency/RequestManager.cs @@ -1,43 +1,38 @@ -using Ordering.Domain.Exceptions; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency +public class RequestManager : IRequestManager { - public class RequestManager : IRequestManager - { - private readonly OrderingContext _context; + private readonly OrderingContext _context; - public RequestManager(OrderingContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + public RequestManager(OrderingContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } - public async Task ExistAsync(Guid id) - { - var request = await _context. - FindAsync(id); + public async Task ExistAsync(Guid id) + { + var request = await _context. + FindAsync(id); - return request != null; - } + return request != null; + } - public async Task CreateRequestForCommandAsync(Guid id) - { - var exists = await ExistAsync(id); + public async Task CreateRequestForCommandAsync(Guid id) + { + var exists = await ExistAsync(id); - var request = exists ? - throw new OrderingDomainException($"Request with {id} already exists") : - new ClientRequest() - { - Id = id, - Name = typeof(T).Name, - Time = DateTime.UtcNow - }; + var request = exists ? + throw new OrderingDomainException($"Request with {id} already exists") : + new ClientRequest() + { + Id = id, + Name = typeof(T).Name, + Time = DateTime.UtcNow + }; - _context.Add(request); + _context.Add(request); - await _context.SaveChangesAsync(); - } + await _context.SaveChangesAsync(); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs b/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs index 8d0ea1d63..571280aba 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs @@ -1,28 +1,21 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -namespace Ordering.Infrastructure +static class MediatorExtension { - static class MediatorExtension + public static async Task DispatchDomainEventsAsync(this IMediator mediator, OrderingContext ctx) { - public static async Task DispatchDomainEventsAsync(this IMediator mediator, OrderingContext ctx) - { - var domainEntities = ctx.ChangeTracker - .Entries() - .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()); + var domainEntities = ctx.ChangeTracker + .Entries() + .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()); - var domainEvents = domainEntities - .SelectMany(x => x.Entity.DomainEvents) - .ToList(); + var domainEvents = domainEntities + .SelectMany(x => x.Entity.DomainEvents) + .ToList(); - domainEntities.ToList() - .ForEach(entity => entity.Entity.ClearDomainEvents()); + domainEntities.ToList() + .ForEach(entity => entity.Entity.ClearDomainEvents()); - foreach (var domainEvent in domainEvents) - await mediator.Publish(domainEvent); - } + foreach (var domainEvent in domainEvents) + await mediator.Publish(domainEvent); } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj b/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj index 36894875e..4c5385d09 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj +++ b/src/Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 @@ -9,11 +9,11 @@ - - - - - + + + + + diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs index f6e6d4a02..243cfadf1 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs @@ -1,156 +1,151 @@ -using MediatR; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using Ordering.Infrastructure; -using Ordering.Infrastructure.EntityConfigurations; -using System; -using System.Data; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; + +public class OrderingContext : DbContext, IUnitOfWork { - public class OrderingContext : DbContext, IUnitOfWork + public const string DEFAULT_SCHEMA = "ordering"; + public DbSet Orders { get; set; } + public DbSet OrderItems { get; set; } + public DbSet Payments { get; set; } + public DbSet Buyers { get; set; } + public DbSet CardTypes { get; set; } + public DbSet OrderStatus { get; set; } + + private readonly IMediator _mediator; + private IDbContextTransaction _currentTransaction; + + public OrderingContext(DbContextOptions options) : base(options) { } + + public IDbContextTransaction GetCurrentTransaction() => _currentTransaction; + + public bool HasActiveTransaction => _currentTransaction != null; + + public OrderingContext(DbContextOptions options, IMediator mediator) : base(options) { - public const string DEFAULT_SCHEMA = "ordering"; - public DbSet Orders { get; set; } - public DbSet OrderItems { get; set; } - public DbSet Payments { get; set; } - public DbSet Buyers { get; set; } - public DbSet CardTypes { get; set; } - public DbSet OrderStatus { get; set; } + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); - private readonly IMediator _mediator; - private IDbContextTransaction _currentTransaction; - public OrderingContext(DbContextOptions options) : base(options) { } + System.Diagnostics.Debug.WriteLine("OrderingContext::ctor ->" + this.GetHashCode()); + } - public IDbContextTransaction GetCurrentTransaction() => _currentTransaction; + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfiguration(new ClientRequestEntityTypeConfiguration()); + modelBuilder.ApplyConfiguration(new PaymentMethodEntityTypeConfiguration()); + modelBuilder.ApplyConfiguration(new OrderEntityTypeConfiguration()); + modelBuilder.ApplyConfiguration(new OrderItemEntityTypeConfiguration()); + modelBuilder.ApplyConfiguration(new CardTypeEntityTypeConfiguration()); + modelBuilder.ApplyConfiguration(new OrderStatusEntityTypeConfiguration()); + modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration()); + } - public bool HasActiveTransaction => _currentTransaction != null; + public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + // Dispatch Domain Events collection. + // Choices: + // A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including + // side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime + // B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions. + // You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers. + await _mediator.DispatchDomainEventsAsync(this); + + // After executing this line all the changes (from the Command Handler and Domain Event Handlers) + // performed through the DbContext will be committed + var result = await base.SaveChangesAsync(cancellationToken); + + return true; + } - public OrderingContext(DbContextOptions options, IMediator mediator) : base(options) - { - _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + public async Task BeginTransactionAsync() + { + if (_currentTransaction != null) return null; + _currentTransaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted); - System.Diagnostics.Debug.WriteLine("OrderingContext::ctor ->" + this.GetHashCode()); - } + return _currentTransaction; + } - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.ApplyConfiguration(new ClientRequestEntityTypeConfiguration()); - modelBuilder.ApplyConfiguration(new PaymentMethodEntityTypeConfiguration()); - modelBuilder.ApplyConfiguration(new OrderEntityTypeConfiguration()); - modelBuilder.ApplyConfiguration(new OrderItemEntityTypeConfiguration()); - modelBuilder.ApplyConfiguration(new CardTypeEntityTypeConfiguration()); - modelBuilder.ApplyConfiguration(new OrderStatusEntityTypeConfiguration()); - modelBuilder.ApplyConfiguration(new BuyerEntityTypeConfiguration()); - } + public async Task CommitTransactionAsync(IDbContextTransaction transaction) + { + if (transaction == null) throw new ArgumentNullException(nameof(transaction)); + if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current"); - public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken)) + try { - // Dispatch Domain Events collection. - // Choices: - // A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including - // side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime - // B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions. - // You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers. - await _mediator.DispatchDomainEventsAsync(this); - - // After executing this line all the changes (from the Command Handler and Domain Event Handlers) - // performed through the DbContext will be committed - var result = await base.SaveChangesAsync(cancellationToken); - - return true; + await SaveChangesAsync(); + transaction.Commit(); } - - public async Task BeginTransactionAsync() + catch { - if (_currentTransaction != null) return null; - - _currentTransaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted); - - return _currentTransaction; + RollbackTransaction(); + throw; } - - public async Task CommitTransactionAsync(IDbContextTransaction transaction) + finally { - if (transaction == null) throw new ArgumentNullException(nameof(transaction)); - if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current"); - - try - { - await SaveChangesAsync(); - transaction.Commit(); - } - catch + if (_currentTransaction != null) { - RollbackTransaction(); - throw; - } - finally - { - if (_currentTransaction != null) - { - _currentTransaction.Dispose(); - _currentTransaction = null; - } + _currentTransaction.Dispose(); + _currentTransaction = null; } } + } - public void RollbackTransaction() + public void RollbackTransaction() + { + try { - try - { - _currentTransaction?.Rollback(); - } - finally + _currentTransaction?.Rollback(); + } + finally + { + if (_currentTransaction != null) { - if (_currentTransaction != null) - { - _currentTransaction.Dispose(); - _currentTransaction = null; - } + _currentTransaction.Dispose(); + _currentTransaction = null; } } } +} + +public class OrderingContextDesignFactory : IDesignTimeDbContextFactory +{ + public OrderingContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;Integrated Security=true"); + + return new OrderingContext(optionsBuilder.Options, new NoMediator()); + } - public class OrderingContextDesignFactory : IDesignTimeDbContextFactory + class NoMediator : IMediator { - public OrderingContext CreateDbContext(string[] args) + public IAsyncEnumerable CreateStream(IStreamRequest request, CancellationToken cancellationToken = default) { - var optionsBuilder = new DbContextOptionsBuilder() - .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.OrderingDb;Integrated Security=true"); + return default(IAsyncEnumerable); + } - return new OrderingContext(optionsBuilder.Options, new NoMediator()); + public IAsyncEnumerable CreateStream(object request, CancellationToken cancellationToken = default) + { + return default(IAsyncEnumerable); } - class NoMediator : IMediator + public Task Publish(TNotification notification, CancellationToken cancellationToken = default(CancellationToken)) where TNotification : INotification { - public Task Publish(TNotification notification, CancellationToken cancellationToken = default(CancellationToken)) where TNotification : INotification - { - return Task.CompletedTask; - } + return Task.CompletedTask; + } - public Task Publish(object notification, CancellationToken cancellationToken = default) - { - return Task.CompletedTask; - } + public Task Publish(object notification, CancellationToken cancellationToken = default) + { + return Task.CompletedTask; + } - public Task Send(IRequest request, CancellationToken cancellationToken = default(CancellationToken)) - { - return Task.FromResult(default(TResponse)); - } + public Task Send(IRequest request, CancellationToken cancellationToken = default(CancellationToken)) + { + return Task.FromResult(default(TResponse)); + } - public Task Send(object request, CancellationToken cancellationToken = default) - { - return Task.FromResult(default(object)); - } + public Task Send(object request, CancellationToken cancellationToken = default) + { + return Task.FromResult(default(object)); } } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs b/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs index 2e7b41bd6..648d2ea09 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs @@ -1,68 +1,54 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using System; -using System.Linq; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories; -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories +public class BuyerRepository + : IBuyerRepository { - public class BuyerRepository - : IBuyerRepository + private readonly OrderingContext _context; + public IUnitOfWork UnitOfWork => _context; + + public BuyerRepository(OrderingContext context) { - private readonly OrderingContext _context; - public IUnitOfWork UnitOfWork - { - get - { - return _context; - } - } + _context = context ?? throw new ArgumentNullException(nameof(context)); + } - public BuyerRepository(OrderingContext context) + public Buyer Add(Buyer buyer) + { + if (buyer.IsTransient()) { - _context = context ?? throw new ArgumentNullException(nameof(context)); + return _context.Buyers + .Add(buyer) + .Entity; } - - public Buyer Add(Buyer buyer) + else { - if (buyer.IsTransient()) - { - return _context.Buyers - .Add(buyer) - .Entity; - } - else - { - return buyer; - } + return buyer; } + } - public Buyer Update(Buyer buyer) - { - return _context.Buyers - .Update(buyer) - .Entity; - } + public Buyer Update(Buyer buyer) + { + return _context.Buyers + .Update(buyer) + .Entity; + } - public async Task FindAsync(string identity) - { - var buyer = await _context.Buyers - .Include(b => b.PaymentMethods) - .Where(b => b.IdentityGuid == identity) - .SingleOrDefaultAsync(); + public async Task FindAsync(string identity) + { + var buyer = await _context.Buyers + .Include(b => b.PaymentMethods) + .Where(b => b.IdentityGuid == identity) + .SingleOrDefaultAsync(); - return buyer; - } + return buyer; + } - public async Task FindByIdAsync(string id) - { - var buyer = await _context.Buyers - .Include(b => b.PaymentMethods) - .Where(b => b.Id == int.Parse(id)) - .SingleOrDefaultAsync(); + public async Task FindByIdAsync(string id) + { + var buyer = await _context.Buyers + .Include(b => b.PaymentMethods) + .Where(b => b.Id == int.Parse(id)) + .SingleOrDefaultAsync(); - return buyer; - } + return buyer; } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs b/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs index 040256cf6..edb9ace1a 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/Repositories/OrderRepository.cs @@ -1,63 +1,49 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories +namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories; + +public class OrderRepository + : IOrderRepository { - public class OrderRepository - : IOrderRepository - { - private readonly OrderingContext _context; + private readonly OrderingContext _context; - public IUnitOfWork UnitOfWork - { - get - { - return _context; - } - } + public IUnitOfWork UnitOfWork => _context; - public OrderRepository(OrderingContext context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + public OrderRepository(OrderingContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } - public Order Add(Order order) - { - return _context.Orders.Add(order).Entity; + public Order Add(Order order) + { + return _context.Orders.Add(order).Entity; - } + } - public async Task GetAsync(int orderId) - { - var order = await _context - .Orders - .Include(x => x.Address) - .FirstOrDefaultAsync(o => o.Id == orderId); - if (order == null) - { - order = _context + public async Task GetAsync(int orderId) + { + var order = await _context .Orders - .Local - .FirstOrDefault(o => o.Id == orderId); - } - if (order != null) - { - await _context.Entry(order) - .Collection(i => i.OrderItems).LoadAsync(); - await _context.Entry(order) - .Reference(i => i.OrderStatus).LoadAsync(); - } - - return order; + .Include(x => x.Address) + .FirstOrDefaultAsync(o => o.Id == orderId); + if (order == null) + { + order = _context + .Orders + .Local + .FirstOrDefault(o => o.Id == orderId); } - - public void Update(Order order) + if (order != null) { - _context.Entry(order).State = EntityState.Modified; + await _context.Entry(order) + .Collection(i => i.OrderItems).LoadAsync(); + await _context.Entry(order) + .Reference(i => i.OrderStatus).LoadAsync(); } + + return order; + } + + public void Update(Order order) + { + _context.Entry(order).State = EntityState.Modified; } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/AutofacModules/ApplicationModule.cs b/src/Services/Ordering/Ordering.SignalrHub/AutofacModules/ApplicationModule.cs index e7b09f636..9d28154ea 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/AutofacModules/ApplicationModule.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/AutofacModules/ApplicationModule.cs @@ -1,26 +1,20 @@ -using Autofac; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Ordering.SignalrHub.IntegrationEvents; -using System.Reflection; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.AutofacModules; -namespace Ordering.SignalrHub.AutofacModules +public class ApplicationModule + : Autofac.Module { - public class ApplicationModule - : Autofac.Module - { - public string QueriesConnectionString { get; } + public string QueriesConnectionString { get; } - public ApplicationModule() - { - } + public ApplicationModule() + { + } - protected override void Load(ContainerBuilder builder) - { + protected override void Load(ContainerBuilder builder) + { - builder.RegisterAssemblyTypes(typeof(OrderStatusChangedToAwaitingValidationIntegrationEvent).GetTypeInfo().Assembly) - .AsClosedTypesOf(typeof(IIntegrationEventHandler<>)); + builder.RegisterAssemblyTypes(typeof(OrderStatusChangedToAwaitingValidationIntegrationEvent).GetTypeInfo().Assembly) + .AsClosedTypesOf(typeof(IIntegrationEventHandler<>)); - } } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile index bb80617ff..33771bf1f 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile +++ b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile.develop b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile.develop index efe636e63..21447fca6 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile.develop +++ b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs b/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs new file mode 100644 index 000000000..5a5a12391 --- /dev/null +++ b/src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs @@ -0,0 +1,35 @@ +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.SignalR; +global using Microsoft.AspNetCore; +global using Azure.Messaging.ServiceBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Logging; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.AutofacModules; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents; +global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; +global using RabbitMQ.Client; +global using Serilog.Context; +global using Serilog; +global using System.IdentityModel.Tokens.Jwt; +global using System.IO; +global using System.Reflection; +global using System.Threading.Tasks; +global using System; diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs index 17e2efa90..341b781ab 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToAwaitingValidationIntegrationEventHandler.cs @@ -1,36 +1,28 @@ -using Microsoft.AspNetCore.SignalR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents; -namespace Ordering.SignalrHub.IntegrationEvents +public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IHubContext _hubContext; - private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly ILogger _logger; - public OrderStatusChangedToAwaitingValidationIntegrationEventHandler( - IHubContext hubContext, - ILogger logger) - { - _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStatusChangedToAwaitingValidationIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _hubContext.Clients - .Group(@event.BuyerName) - .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); - } + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); } } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs index 829ec39b8..aba5091b9 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCancelledIntegrationEventHandler.cs @@ -1,37 +1,28 @@ -using Microsoft.AspNetCore.SignalR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using Ordering.SignalrHub.IntegrationEvents.Events; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; -namespace Ordering.SignalrHub.IntegrationEvents.EventHandling +public class OrderStatusChangedToCancelledIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStatusChangedToCancelledIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IHubContext _hubContext; - private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly ILogger _logger; - public OrderStatusChangedToCancelledIntegrationEventHandler( - IHubContext hubContext, - ILogger logger) - { - _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStatusChangedToCancelledIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToCancelledIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToCancelledIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _hubContext.Clients - .Group(@event.BuyerName) - .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); - } + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); } } } \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs index 836e02d3c..03fc04356 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToPaidIntegrationEventHandler.cs @@ -1,37 +1,28 @@ -using Microsoft.AspNetCore.SignalR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using Ordering.SignalrHub.IntegrationEvents.Events; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; -namespace Ordering.SignalrHub.IntegrationEvents.EventHandling +public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IHubContext _hubContext; - private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly ILogger _logger; - public OrderStatusChangedToPaidIntegrationEventHandler( - IHubContext hubContext, - ILogger logger) - { - _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStatusChangedToPaidIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _hubContext.Clients - .Group(@event.BuyerName) - .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); - } + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); } } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs index 40664c268..663f7ae3a 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToShippedIntegrationEventHandler.cs @@ -1,37 +1,28 @@ -using Microsoft.AspNetCore.SignalR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using Ordering.SignalrHub.IntegrationEvents.Events; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; -namespace Ordering.SignalrHub.IntegrationEvents.EventHandling +public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler - { - private readonly IHubContext _hubContext; - private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly ILogger _logger; - public OrderStatusChangedToShippedIntegrationEventHandler( - IHubContext hubContext, - ILogger logger) - { - _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStatusChangedToShippedIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _hubContext.Clients - .Group(@event.BuyerName) - .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); - } + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); } } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs index 3ffddfff9..aa662065d 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs @@ -1,38 +1,29 @@ -using Microsoft.AspNetCore.SignalR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using Ordering.SignalrHub.IntegrationEvents.Events; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; -namespace Ordering.SignalrHub.IntegrationEvents.EventHandling +public class OrderStatusChangedToStockConfirmedIntegrationEventHandler : + IIntegrationEventHandler { - public class OrderStatusChangedToStockConfirmedIntegrationEventHandler : - IIntegrationEventHandler - { - private readonly IHubContext _hubContext; - private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly ILogger _logger; - public OrderStatusChangedToStockConfirmedIntegrationEventHandler( - IHubContext hubContext, - ILogger logger) - { - _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStatusChangedToStockConfirmedIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _hubContext.Clients - .Group(@event.BuyerName) - .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); - } + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); } } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs index e9109939e..0f8042013 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToSubmittedIntegrationEventHandler.cs @@ -1,38 +1,29 @@ -using Microsoft.AspNetCore.SignalR; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using Ordering.SignalrHub.IntegrationEvents.Events; -using Serilog.Context; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; -namespace Ordering.SignalrHub.IntegrationEvents.EventHandling +public class OrderStatusChangedToSubmittedIntegrationEventHandler : + IIntegrationEventHandler { - public class OrderStatusChangedToSubmittedIntegrationEventHandler : - IIntegrationEventHandler - { - private readonly IHubContext _hubContext; - private readonly ILogger _logger; + private readonly IHubContext _hubContext; + private readonly ILogger _logger; - public OrderStatusChangedToSubmittedIntegrationEventHandler( - IHubContext hubContext, - ILogger logger) - { - _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public OrderStatusChangedToSubmittedIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public async Task Handle(OrderStatusChangedToSubmittedIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToSubmittedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - await _hubContext.Clients - .Group(@event.BuyerName) - .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); - } + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); } } -} \ No newline at end of file +} diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs index dc1727951..3afcf8f36 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToAwaitingValidationIntegrationEvent.cs @@ -1,18 +1,16 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents; -namespace Ordering.SignalrHub.IntegrationEvents +public record OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } + diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs index 1ea290082..5df74ac78 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCancelledIntegrationEvent.cs @@ -1,18 +1,16 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; -namespace Ordering.SignalrHub.IntegrationEvents.Events +public record OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToCancelledIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToCancelledIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } + diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs index e3bf88190..63246835d 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToPaidIntegrationEvent.cs @@ -1,19 +1,16 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; -namespace Ordering.SignalrHub.IntegrationEvents.Events +public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToPaidIntegrationEvent(int orderId, - string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToPaidIntegrationEvent(int orderId, + string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs index 436b5a95a..9306d198e 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToShippedIntegrationEvent.cs @@ -1,18 +1,16 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; -namespace Ordering.SignalrHub.IntegrationEvents.Events +public record OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } + diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs index 137967ff6..896ef34cb 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs @@ -1,18 +1,15 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; -namespace Ordering.SignalrHub.IntegrationEvents.Events +public record OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs index 0d2de4abe..23f01044e 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToSubmittedIntegrationEvent.cs @@ -1,18 +1,15 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; -namespace Ordering.SignalrHub.IntegrationEvents.Events +public record OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public string OrderStatus { get; } - public string BuyerName { get; } + public int OrderId { get; } + public string OrderStatus { get; } + public string BuyerName { get; } - public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToSubmittedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs index 7696a4da1..9f545bba4 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/NotificationHub.cs @@ -1,24 +1,18 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.SignalR; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; -namespace Ordering.SignalrHub +[Authorize] +public class NotificationsHub : Hub { - [Authorize] - public class NotificationsHub : Hub - { - public override async Task OnConnectedAsync() - { - await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name); - await base.OnConnectedAsync(); - } + public override async Task OnConnectedAsync() + { + await Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name); + await base.OnConnectedAsync(); + } - public override async Task OnDisconnectedAsync(Exception ex) - { - await Groups.RemoveFromGroupAsync(Context.ConnectionId, Context.User.Identity.Name); - await base.OnDisconnectedAsync(ex); - } + public override async Task OnDisconnectedAsync(Exception ex) + { + await Groups.RemoveFromGroupAsync(Context.ConnectionId, Context.User.Identity.Name); + await base.OnDisconnectedAsync(ex); } } diff --git a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj index c20772414..9b9579855 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj +++ b/src/Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj @@ -1,11 +1,10 @@  - net5.0 + net6.0 ..\..\..\..\docker-compose.dcproj false - true - preview + true @@ -13,26 +12,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Ordering/Ordering.SignalrHub/Program.cs b/src/Services/Ordering/Ordering.SignalrHub/Program.cs index d73e1da2a..b2ee22ff2 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Program.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/Program.cs @@ -1,12 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Serilog; -using System; -using System.IO; -using Ordering.SignalrHub; - -var configuration = GetConfiguration(); +var configuration = GetConfiguration(); Log.Logger = CreateSerilogLogger(configuration); @@ -64,7 +56,7 @@ static IConfiguration GetConfiguration() return builder.Build(); } -public class Program +public partial class Program { public static string Namespace = typeof(Startup).Namespace; public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); diff --git a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs index a4a5d08c7..b57f4477e 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs @@ -1,274 +1,249 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.Azure.ServiceBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Logging; -using Ordering.SignalrHub.AutofacModules; -using Ordering.SignalrHub.IntegrationEvents; -using Ordering.SignalrHub.IntegrationEvents.EventHandling; -using Ordering.SignalrHub.IntegrationEvents.Events; -using RabbitMQ.Client; -using System; -using System.IdentityModel.Tokens.Jwt; -using System.Threading.Tasks; - -namespace Ordering.SignalrHub +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } + + public IConfiguration Configuration { get; } - public IConfiguration Configuration { get; } + // This method gets called by the runtime. Use this method to add services to the container. + // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 + public IServiceProvider ConfigureServices(IServiceCollection services) + { + services + .AddCustomHealthCheck(Configuration) + .AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .AllowAnyMethod() + .AllowAnyHeader() + .SetIsOriginAllowed((host) => true) + .AllowCredentials()); + }); - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public IServiceProvider ConfigureServices(IServiceCollection services) + if (Configuration.GetValue("IsClusterEnv") == bool.TrueString) { services - .AddCustomHealthCheck(Configuration) - .AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .AllowAnyMethod() - .AllowAnyHeader() - .SetIsOriginAllowed((host) => true) - .AllowCredentials()); - }); - - if (Configuration.GetValue("IsClusterEnv") == bool.TrueString) - { - services - .AddSignalR() - .AddStackExchangeRedis(Configuration["SignalrStoreConnectionString"]); - } - else - { - services.AddSignalR(); - } + .AddSignalR() + .AddStackExchangeRedis(Configuration["SignalrStoreConnectionString"]); + } + else + { + services.AddSignalR(); + } - if (Configuration.GetValue("AzureServiceBusEnabled")) + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var serviceBusConnectionString = Configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); + var serviceBusConnectionString = Configuration["EventBusConnection"]; - var subscriptionClientName = Configuration["SubscriptionClientName"]; + var subscriptionClientName = Configuration["SubscriptionClientName"]; - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); - }); - } - else + return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); + }); + } + else + { + services.AddSingleton(sp => { - services.AddSingleton(sp => + var logger = sp.GetRequiredService>(); + + + var factory = new ConnectionFactory() { - var logger = sp.GetRequiredService>(); + HostName = Configuration["EventBusConnection"], + DispatchConsumersAsync = true + }; + if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) + { + factory.UserName = Configuration["EventBusUserName"]; + } - var factory = new ConnectionFactory() - { - HostName = Configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; + if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) + { + factory.Password = Configuration["EventBusPassword"]; + } - if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) - { - factory.UserName = Configuration["EventBusUserName"]; - } + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } - if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) - { - factory.Password = Configuration["EventBusPassword"]; - } + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); + }); + } - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } + ConfigureAuthService(services); - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } + RegisterEventBus(services); - ConfigureAuthService(services); + services.AddOptions(); - RegisterEventBus(services); + //configure autofac + var container = new ContainerBuilder(); + container.RegisterModule(new ApplicationModule()); + container.Populate(services); - services.AddOptions(); + return new AutofacServiceProvider(container.Build()); + } - //configure autofac - var container = new ContainerBuilder(); - container.RegisterModule(new ApplicationModule()); - container.Populate(services); + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + { + //loggerFactory.AddConsole(Configuration.GetSection("Logging")); + //loggerFactory.AddDebug(); + //loggerFactory.AddAzureWebAppDiagnostics(); + //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - return new AutofacServiceProvider(container.Build()); - } + var pathBase = Configuration["PATH_BASE"]; - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + if (!string.IsNullOrEmpty(pathBase)) { - //loggerFactory.AddConsole(Configuration.GetSection("Logging")); - //loggerFactory.AddDebug(); - //loggerFactory.AddAzureWebAppDiagnostics(); - //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); + app.UsePathBase(pathBase); + } - var pathBase = Configuration["PATH_BASE"]; + app.UseRouting(); + app.UseCors("CorsPolicy"); + app.UseAuthentication(); + app.UseAuthorization(); - if (!string.IsNullOrEmpty(pathBase)) + app.UseEndpoints(endpoints => + { + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() { - loggerFactory.CreateLogger().LogDebug("Using PATH BASE '{pathBase}'", pathBase); - app.UsePathBase(pathBase); - } - - app.UseRouting(); - app.UseCors("CorsPolicy"); - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseEndpoints(endpoints => + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); - endpoints.MapHub("/hub/notificationhub"); + Predicate = r => r.Name.Contains("self") }); + endpoints.MapHub("/hub/notificationhub"); + }); - ConfigureEventBus(app); - } + ConfigureEventBus(app); + } - private void ConfigureEventBus(IApplicationBuilder app) - { - var eventBus = app.ApplicationServices.GetRequiredService(); - - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - } + private void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + + eventBus.Subscribe(); + eventBus.Subscribe(); + eventBus.Subscribe(); + eventBus.Subscribe(); + eventBus.Subscribe(); + eventBus.Subscribe(); + } - private void ConfigureAuthService(IServiceCollection services) - { - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + private void ConfigureAuthService(IServiceCollection services) + { + // prevent from mapping "sub" claim to nameidentifier. + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - var identityUrl = Configuration.GetValue("IdentityUrl"); + var identityUrl = Configuration.GetValue("IdentityUrl"); - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(options => + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "orders.signalrhub"; + options.Events = new JwtBearerEvents { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "orders.signalrhub"; - options.Events = new JwtBearerEvents + OnMessageReceived = context => { - OnMessageReceived = context => + var accessToken = context.Request.Query["access_token"]; + + var path = context.HttpContext.Request.Path; + if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/hub/notificationhub"))) { - var accessToken = context.Request.Query["access_token"]; - - var path = context.HttpContext.Request.Path; - if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/hub/notificationhub"))) - { - context.Token = accessToken; - } - return Task.CompletedTask; + context.Token = accessToken; } - }; - }); - } + return Task.CompletedTask; + } + }; + }); + } - private void RegisterEventBus(IServiceCollection services) + private void RegisterEventBus(IServiceCollection services) + { + if (Configuration.GetValue("AzureServiceBusEnabled")) { - if (Configuration.GetValue("AzureServiceBusEnabled")) + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, iLifetimeScope); - }); - } - else + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); + }); + } + else + { + services.AddSingleton(sp => { - services.AddSingleton(sp => + var subscriptionClientName = Configuration["SubscriptionClientName"]; + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) { - var subscriptionClientName = Configuration["SubscriptionClientName"]; - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } - - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } - services.AddSingleton(); + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); } + + services.AddSingleton(); } +} - public static class CustomExtensionMethods +public static class CustomExtensionMethods +{ + public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var hcBuilder = services.AddHealthChecks(); + var hcBuilder = services.AddHealthChecks(); - hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); + hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "signalr-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "signalr-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } - - return services; + if (configuration.GetValue("AzureServiceBusEnabled")) + { + hcBuilder + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "signalr-servicebus-check", + tags: new string[] { "servicebus" }); + } + else + { + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "signalr-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); } + + return services; } } diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs index 62818115d..1b7d38864 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Application/IdentifiedCommandHandlerTest.cs @@ -1,91 +1,79 @@ -using System; +namespace UnitTest.Ordering.Application; -namespace UnitTest.Ordering.Application +public class IdentifiedCommandHandlerTest { - using global::Ordering.API.Application.Models; - using MediatR; - using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; - using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; - using Microsoft.Extensions.Logging; - using Moq; - using System.Collections.Generic; - using System.Threading.Tasks; - using Xunit; - public class IdentifiedCommandHandlerTest - { - private readonly Mock _requestManager; - private readonly Mock _mediator; - private readonly Mock>> _loggerMock; + private readonly Mock _requestManager; + private readonly Mock _mediator; + private readonly Mock>> _loggerMock; - public IdentifiedCommandHandlerTest() - { - _requestManager = new Mock(); - _mediator = new Mock(); - _loggerMock = new Mock>>(); - } + public IdentifiedCommandHandlerTest() + { + _requestManager = new Mock(); + _mediator = new Mock(); + _loggerMock = new Mock>>(); + } - [Fact] - public async Task Handler_sends_command_when_order_no_exists() - { - // Arrange - var fakeGuid = Guid.NewGuid(); - var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); + [Fact] + public async Task Handler_sends_command_when_order_no_exists() + { + // Arrange + var fakeGuid = Guid.NewGuid(); + var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); - _requestManager.Setup(x => x.ExistAsync(It.IsAny())) - .Returns(Task.FromResult(false)); + _requestManager.Setup(x => x.ExistAsync(It.IsAny())) + .Returns(Task.FromResult(false)); - _mediator.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) - .Returns(Task.FromResult(true)); + _mediator.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); - //Act - var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object, _loggerMock.Object); - var cltToken = new System.Threading.CancellationToken(); - var result = await handler.Handle(fakeOrderCmd, cltToken); + //Act + var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object, _loggerMock.Object); + var cltToken = new System.Threading.CancellationToken(); + var result = await handler.Handle(fakeOrderCmd, cltToken); - //Assert - Assert.True(result); - _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Once()); - } + //Assert + Assert.True(result); + _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Once()); + } - [Fact] - public async Task Handler_sends_no_command_when_order_already_exists() - { - // Arrange - var fakeGuid = Guid.NewGuid(); - var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); + [Fact] + public async Task Handler_sends_no_command_when_order_already_exists() + { + // Arrange + var fakeGuid = Guid.NewGuid(); + var fakeOrderCmd = new IdentifiedCommand(FakeOrderRequest(), fakeGuid); - _requestManager.Setup(x => x.ExistAsync(It.IsAny())) - .Returns(Task.FromResult(true)); + _requestManager.Setup(x => x.ExistAsync(It.IsAny())) + .Returns(Task.FromResult(true)); - _mediator.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) - .Returns(Task.FromResult(true)); + _mediator.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); - //Act - var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object, _loggerMock.Object); - var cltToken = new System.Threading.CancellationToken(); - var result = await handler.Handle(fakeOrderCmd, cltToken); + //Act + var handler = new IdentifiedCommandHandler(_mediator.Object, _requestManager.Object, _loggerMock.Object); + var cltToken = new System.Threading.CancellationToken(); + var result = await handler.Handle(fakeOrderCmd, cltToken); - //Assert - Assert.False(result); - _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Never()); - } + //Assert + Assert.False(result); + _mediator.Verify(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken)), Times.Never()); + } - private CreateOrderCommand FakeOrderRequest(Dictionary args = null) - { - return new CreateOrderCommand( - new List(), - userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, - userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, - city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, - street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, - state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, - country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, - zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, - cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", - cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, - cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", - cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", - cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); - } + private CreateOrderCommand FakeOrderRequest(Dictionary args = null) + { + return new CreateOrderCommand( + new List(), + userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, + userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, + city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, + street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, + state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, + country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, + zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, + cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", + cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, + cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", + cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", + cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); } } diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs index 78d7dbed7..184a5f5d2 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Application/NewOrderCommandHandlerTest.cs @@ -1,97 +1,83 @@ -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; -using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Moq; -using System; -using System.Threading; -using System.Threading.Tasks; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents; + +namespace UnitTest.Ordering.Application; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -namespace UnitTest.Ordering.Application +public class NewOrderRequestHandlerTest { - using global::Ordering.API.Application.IntegrationEvents; - using global::Ordering.API.Application.Models; - using MediatR; - using Microsoft.Extensions.Logging; - using System.Collections.Generic; - using Xunit; - - public class NewOrderRequestHandlerTest + private readonly Mock _orderRepositoryMock; + private readonly Mock _identityServiceMock; + private readonly Mock _mediator; + private readonly Mock _orderingIntegrationEventService; + + public NewOrderRequestHandlerTest() + { + + _orderRepositoryMock = new Mock(); + _identityServiceMock = new Mock(); + _orderingIntegrationEventService = new Mock(); + _mediator = new Mock(); + } + + [Fact] + public async Task Handle_return_false_if_order_is_not_persisted() + { + var buyerId = "1234"; + + var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary + { ["cardExpiration"] = DateTime.Now.AddYears(1) }); + + _orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny())) + .Returns(Task.FromResult(FakeOrder())); + + _orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) + .Returns(Task.FromResult(1)); + + _identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId); + + var LoggerMock = new Mock>(); + //Act + var handler = new CreateOrderCommandHandler(_mediator.Object, _orderingIntegrationEventService.Object, _orderRepositoryMock.Object, _identityServiceMock.Object, LoggerMock.Object); + var cltToken = new System.Threading.CancellationToken(); + var result = await handler.Handle(fakeOrderCmd, cltToken); + + //Assert + Assert.False(result); + } + + [Fact] + public void Handle_throws_exception_when_no_buyerId() + { + //Assert + Assert.Throws(() => new Buyer(string.Empty, string.Empty)); + } + + private Buyer FakeBuyer() + { + return new Buyer(Guid.NewGuid().ToString(), "1"); + } + + private Order FakeOrder() + { + return new Order("1", "fakeName", new Address("street", "city", "state", "country", "zipcode"), 1, "12", "111", "fakeName", DateTime.Now.AddYears(1)); + } + + private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary args = null) { - private readonly Mock _orderRepositoryMock; - private readonly Mock _identityServiceMock; - private readonly Mock _mediator; - private readonly Mock _orderingIntegrationEventService; - - public NewOrderRequestHandlerTest() - { - - _orderRepositoryMock = new Mock(); - _identityServiceMock = new Mock(); - _orderingIntegrationEventService = new Mock(); - _mediator = new Mock(); - } - - [Fact] - public async Task Handle_return_false_if_order_is_not_persisted() - { - var buyerId = "1234"; - - var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary - { ["cardExpiration"] = DateTime.Now.AddYears(1) }); - - _orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny())) - .Returns(Task.FromResult(FakeOrder())); - - _orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken))) - .Returns(Task.FromResult(1)); - - _identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId); - - var LoggerMock = new Mock>(); - //Act - var handler = new CreateOrderCommandHandler(_mediator.Object, _orderingIntegrationEventService.Object, _orderRepositoryMock.Object, _identityServiceMock.Object, LoggerMock.Object); - var cltToken = new System.Threading.CancellationToken(); - var result = await handler.Handle(fakeOrderCmd, cltToken); - - //Assert - Assert.False(result); - } - - [Fact] - public void Handle_throws_exception_when_no_buyerId() - { - //Assert - Assert.Throws(() => new Buyer(string.Empty, string.Empty)); - } - - private Buyer FakeBuyer() - { - return new Buyer(Guid.NewGuid().ToString(), "1"); - } - - private Order FakeOrder() - { - return new Order("1", "fakeName", new Address("street", "city", "state", "country", "zipcode"), 1, "12", "111", "fakeName", DateTime.Now.AddYears(1)); - } - - private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary args = null) - { - return new CreateOrderCommand( - new List(), - userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, - userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, - city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, - street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, - state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, - country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, - zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, - cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", - cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, - cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", - cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", - cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); - } + return new CreateOrderCommand( + new List(), + userId: args != null && args.ContainsKey("userId") ? (string)args["userId"] : null, + userName: args != null && args.ContainsKey("userName") ? (string)args["userName"] : null, + city: args != null && args.ContainsKey("city") ? (string)args["city"] : null, + street: args != null && args.ContainsKey("street") ? (string)args["street"] : null, + state: args != null && args.ContainsKey("state") ? (string)args["state"] : null, + country: args != null && args.ContainsKey("country") ? (string)args["country"] : null, + zipcode: args != null && args.ContainsKey("zipcode") ? (string)args["zipcode"] : null, + cardNumber: args != null && args.ContainsKey("cardNumber") ? (string)args["cardNumber"] : "1234", + cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue, + cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123", + cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX", + cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0); } } diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs index 26281e110..cfa14a3ec 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs @@ -1,148 +1,134 @@ -using MediatR; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +namespace UnitTest.Ordering.Application; + using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; -using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; -using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; -using Microsoft.Extensions.Logging; -using Moq; -using Ordering.API.Application.Commands; -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace UnitTest.Ordering.Application + +public class OrdersWebApiTest { - public class OrdersWebApiTest + private readonly Mock _mediatorMock; + private readonly Mock _orderQueriesMock; + private readonly Mock _identityServiceMock; + private readonly Mock> _loggerMock; + + public OrdersWebApiTest() + { + _mediatorMock = new Mock(); + _orderQueriesMock = new Mock(); + _identityServiceMock = new Mock(); + _loggerMock = new Mock>(); + } + + [Fact] + public async Task Cancel_order_with_requestId_success() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + + } + + [Fact] + public async Task Cancel_order_bad_request() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), String.Empty) as BadRequestResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); + } + + [Fact] + public async Task Ship_order_with_requestId_success() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + + } + + [Fact] + public async Task Ship_order_bad_request() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), String.Empty) as BadRequestResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); + } + + [Fact] + public async Task Get_orders_success() + { + //Arrange + var fakeDynamicResult = Enumerable.Empty(); + + _identityServiceMock.Setup(x => x.GetUserIdentity()) + .Returns(Guid.NewGuid().ToString()); + + _orderQueriesMock.Setup(x => x.GetOrdersFromUserAsync(Guid.NewGuid())) + .Returns(Task.FromResult(fakeDynamicResult)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.GetOrdersAsync(); + + //Assert + Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); + } + + [Fact] + public async Task Get_order_success() { - private readonly Mock _mediatorMock; - private readonly Mock _orderQueriesMock; - private readonly Mock _identityServiceMock; - private readonly Mock> _loggerMock; - - public OrdersWebApiTest() - { - _mediatorMock = new Mock(); - _orderQueriesMock = new Mock(); - _identityServiceMock = new Mock(); - _loggerMock = new Mock>(); - } - - [Fact] - public async Task Cancel_order_with_requestId_success() - { - //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) - .Returns(Task.FromResult(true)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; - - //Assert - Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); - - } - - [Fact] - public async Task Cancel_order_bad_request() - { - //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(CancellationToken))) - .Returns(Task.FromResult(true)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.CancelOrderAsync(new CancelOrderCommand(1), String.Empty) as BadRequestResult; - - //Assert - Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); - } - - [Fact] - public async Task Ship_order_with_requestId_success() - { - //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) - .Returns(Task.FromResult(true)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), Guid.NewGuid().ToString()) as OkResult; - - //Assert - Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); - - } - - [Fact] - public async Task Ship_order_bad_request() - { - //Arrange - _mediatorMock.Setup(x => x.Send(It.IsAny>(), default(System.Threading.CancellationToken))) - .Returns(Task.FromResult(true)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.ShipOrderAsync(new ShipOrderCommand(1), String.Empty) as BadRequestResult; - - //Assert - Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.BadRequest); - } - - [Fact] - public async Task Get_orders_success() - { - //Arrange - var fakeDynamicResult = Enumerable.Empty(); - - _identityServiceMock.Setup(x => x.GetUserIdentity()) - .Returns(Guid.NewGuid().ToString()); - - _orderQueriesMock.Setup(x => x.GetOrdersFromUserAsync(Guid.NewGuid())) - .Returns(Task.FromResult(fakeDynamicResult)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.GetOrdersAsync(); - - //Assert - Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); - } - - [Fact] - public async Task Get_order_success() - { - //Arrange - var fakeOrderId = 123; - var fakeDynamicResult = new Order(); - _orderQueriesMock.Setup(x => x.GetOrderAsync(It.IsAny())) - .Returns(Task.FromResult(fakeDynamicResult)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.GetOrderAsync(fakeOrderId) as OkObjectResult; - - //Assert - Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); - } - - [Fact] - public async Task Get_cardTypes_success() - { - //Arrange - var fakeDynamicResult = Enumerable.Empty(); - _orderQueriesMock.Setup(x => x.GetCardTypesAsync()) - .Returns(Task.FromResult(fakeDynamicResult)); - - //Act - var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); - var actionResult = await orderController.GetCardTypesAsync(); - - //Assert - Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); - } + //Arrange + var fakeOrderId = 123; + var fakeDynamicResult = new Order(); + _orderQueriesMock.Setup(x => x.GetOrderAsync(It.IsAny())) + .Returns(Task.FromResult(fakeDynamicResult)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.GetOrderAsync(fakeOrderId) as OkObjectResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + } + + [Fact] + public async Task Get_cardTypes_success() + { + //Arrange + var fakeDynamicResult = Enumerable.Empty(); + _orderQueriesMock.Setup(x => x.GetCardTypesAsync()) + .Returns(Task.FromResult(fakeDynamicResult)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.GetCardTypesAsync(); + + //Assert + Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); } } diff --git a/src/Services/Ordering/Ordering.UnitTests/Builders.cs b/src/Services/Ordering/Ordering.UnitTests/Builders.cs index 2e9415274..8ecd66cbd 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Builders.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Builders.cs @@ -1,48 +1,46 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using System; +namespace UnitTest.Ordering; -namespace UnitTest.Ordering +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + +public class AddressBuilder { - public class AddressBuilder + public Address Build() { - public Address Build() - { - return new Address("street", "city", "state", "country", "zipcode"); - } + return new Address("street", "city", "state", "country", "zipcode"); } +} - public class OrderBuilder - { - private readonly Order order; +public class OrderBuilder +{ + private readonly Order order; - public OrderBuilder(Address address) - { - order = new Order( - "userId", - "fakeName", - address, - cardTypeId: 5, - cardNumber: "12", - cardSecurityNumber: "123", - cardHolderName: "name", - cardExpiration: DateTime.UtcNow); - } + public OrderBuilder(Address address) + { + order = new Order( + "userId", + "fakeName", + address, + cardTypeId: 5, + cardNumber: "12", + cardSecurityNumber: "123", + cardHolderName: "name", + cardExpiration: DateTime.UtcNow); + } - public OrderBuilder AddOne( - int productId, - string productName, - decimal unitPrice, - decimal discount, - string pictureUrl, - int units = 1) - { - order.AddOrderItem(productId, productName, unitPrice, discount, pictureUrl, units); - return this; - } + public OrderBuilder AddOne( + int productId, + string productName, + decimal unitPrice, + decimal discount, + string pictureUrl, + int units = 1) + { + order.AddOrderItem(productId, productName, unitPrice, discount, pictureUrl, units); + return this; + } - public Order Build() - { - return order; - } + public Order Build() + { + return order; } } diff --git a/src/Services/Ordering/Ordering.UnitTests/Domain/BuyerAggregateTest.cs b/src/Services/Ordering/Ordering.UnitTests/Domain/BuyerAggregateTest.cs index 7f3832059..e8132a15f 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Domain/BuyerAggregateTest.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Domain/BuyerAggregateTest.cs @@ -1,9 +1,4 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Ordering.Domain.Exceptions; -using System; -using Xunit; - -public class BuyerAggregateTest +public class BuyerAggregateTest { public BuyerAggregateTest() { } diff --git a/src/Services/Ordering/Ordering.UnitTests/Domain/OrderAggregateTest.cs b/src/Services/Ordering/Ordering.UnitTests/Domain/OrderAggregateTest.cs index 105d64079..676c05fd8 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Domain/OrderAggregateTest.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Domain/OrderAggregateTest.cs @@ -1,10 +1,6 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; -using Ordering.Domain.Events; -using Ordering.Domain.Exceptions; -using System; -using UnitTest.Ordering; -using Xunit; +namespace Ordering.UnitTests.Domain; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; public class OrderAggregateTest { public OrderAggregateTest() diff --git a/src/Services/Ordering/Ordering.UnitTests/Domain/SeedWork/ValueObjectTests.cs b/src/Services/Ordering/Ordering.UnitTests/Domain/SeedWork/ValueObjectTests.cs index bbfa340d2..d4811062f 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Domain/SeedWork/ValueObjectTests.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Domain/SeedWork/ValueObjectTests.cs @@ -1,189 +1,182 @@ -using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; -using System; -using System.Collections.Generic; -using System.Linq; -using Xunit; +namespace Ordering.UnitTests.Domain.SeedWork; -namespace Ordering.UnitTests.Domain.SeedWork +public class ValueObjectTests { - public class ValueObjectTests - { - public ValueObjectTests() - { } + public ValueObjectTests() + { } - [Theory] - [MemberData(nameof(EqualValueObjects))] - public void Equals_EqualValueObjects_ReturnsTrue(ValueObject instanceA, ValueObject instanceB, string reason) - { - // Act - var result = EqualityComparer.Default.Equals(instanceA, instanceB); + [Theory] + [MemberData(nameof(EqualValueObjects))] + public void Equals_EqualValueObjects_ReturnsTrue(ValueObject instanceA, ValueObject instanceB, string reason) + { + // Act + var result = EqualityComparer.Default.Equals(instanceA, instanceB); - // Assert - Assert.True(result, reason); - } + // Assert + Assert.True(result, reason); + } - [Theory] - [MemberData(nameof(NonEqualValueObjects))] - public void Equals_NonEqualValueObjects_ReturnsFalse(ValueObject instanceA, ValueObject instanceB, string reason) - { - // Act - var result = EqualityComparer.Default.Equals(instanceA, instanceB); + [Theory] + [MemberData(nameof(NonEqualValueObjects))] + public void Equals_NonEqualValueObjects_ReturnsFalse(ValueObject instanceA, ValueObject instanceB, string reason) + { + // Act + var result = EqualityComparer.Default.Equals(instanceA, instanceB); - // Assert - Assert.False(result, reason); - } + // Assert + Assert.False(result, reason); + } - private static readonly ValueObject APrettyValueObject = new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")); + private static readonly ValueObject APrettyValueObject = new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")); - public static readonly TheoryData EqualValueObjects = new TheoryData + public static readonly TheoryData EqualValueObjects = new TheoryData + { { - { - null, - null, - "they should be equal because they are both null" - }, - { - APrettyValueObject, - APrettyValueObject, - "they should be equal because they are the same object" - }, - { - new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), - new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), - "they should be equal because they have equal members" - }, - { - new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto"), - new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto2"), - "they should be equal because all equality components are equal, even though an additional member was set" - }, - { - new ValueObjectB(1, "2", 1, 2, 3 ), - new ValueObjectB(1, "2", 1, 2, 3 ), - "they should be equal because all equality components are equal, including the 'C' list" - } - }; + null, + null, + "they should be equal because they are both null" + }, + { + APrettyValueObject, + APrettyValueObject, + "they should be equal because they are the same object" + }, + { + new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), + new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3")), + "they should be equal because they have equal members" + }, + { + new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto"), + new ValueObjectA(1, "2", Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), new ComplexObject(2, "3"), notAnEqualityComponent: "xpto2"), + "they should be equal because all equality components are equal, even though an additional member was set" + }, + { + new ValueObjectB(1, "2", 1, 2, 3 ), + new ValueObjectB(1, "2", 1, 2, 3 ), + "they should be equal because all equality components are equal, including the 'C' list" + } + }; - public static readonly TheoryData NonEqualValueObjects = new TheoryData + public static readonly TheoryData NonEqualValueObjects = new TheoryData + { { - { - new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), - new ValueObjectA(a: 2, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), - "they should not be equal because the 'A' member on ValueObjectA is different among them" - }, - { - new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), - new ValueObjectA(a: 1, b: null, c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), - "they should not be equal because the 'B' member on ValueObjectA is different among them" - }, - { - new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), - new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 3, b: "3")), - "they should not be equal because the 'A' member on ValueObjectA's 'D' member is different among them" - }, - { - new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), - new ValueObjectB(a: 1, b: "2"), - "they should not be equal because they are not of the same type" - }, - { - new ValueObjectB(1, "2", 1, 2, 3 ), - new ValueObjectB(1, "2", 1, 2, 3, 4 ), - "they should be not be equal because the 'C' list contains one additional value" - }, - { - new ValueObjectB(1, "2", 1, 2, 3, 5 ), - new ValueObjectB(1, "2", 1, 2, 3 ), - "they should be not be equal because the 'C' list contains one additional value" - }, - { - new ValueObjectB(1, "2", 1, 2, 3, 5 ), - new ValueObjectB(1, "2", 1, 2, 3, 4 ), - "they should be not be equal because the 'C' lists are not equal" - } + new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), + new ValueObjectA(a: 2, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), + "they should not be equal because the 'A' member on ValueObjectA is different among them" + }, + { + new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), + new ValueObjectA(a: 1, b: null, c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(2, "3")), + "they should not be equal because the 'B' member on ValueObjectA is different among them" + }, + { + new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), + new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 3, b: "3")), + "they should not be equal because the 'A' member on ValueObjectA's 'D' member is different among them" + }, + { + new ValueObjectA(a: 1, b: "2", c: Guid.Parse("97ea43f0-6fef-4fb7-8c67-9114a7ff6ec0"), d: new ComplexObject(a: 2, b: "3")), + new ValueObjectB(a: 1, b: "2"), + "they should not be equal because they are not of the same type" + }, + { + new ValueObjectB(1, "2", 1, 2, 3 ), + new ValueObjectB(1, "2", 1, 2, 3, 4 ), + "they should be not be equal because the 'C' list contains one additional value" + }, + { + new ValueObjectB(1, "2", 1, 2, 3, 5 ), + new ValueObjectB(1, "2", 1, 2, 3 ), + "they should be not be equal because the 'C' list contains one additional value" + }, + { + new ValueObjectB(1, "2", 1, 2, 3, 5 ), + new ValueObjectB(1, "2", 1, 2, 3, 4 ), + "they should be not be equal because the 'C' lists are not equal" + } - }; + }; - private class ValueObjectA : ValueObject + private class ValueObjectA : ValueObject + { + public ValueObjectA(int a, string b, Guid c, ComplexObject d, string notAnEqualityComponent = null) { - public ValueObjectA(int a, string b, Guid c, ComplexObject d, string notAnEqualityComponent = null) - { - A = a; - B = b; - C = c; - D = d; - NotAnEqualityComponent = notAnEqualityComponent; - } + A = a; + B = b; + C = c; + D = d; + NotAnEqualityComponent = notAnEqualityComponent; + } - public int A { get; } - public string B { get; } - public Guid C { get; } - public ComplexObject D { get; } - public string NotAnEqualityComponent { get; } + public int A { get; } + public string B { get; } + public Guid C { get; } + public ComplexObject D { get; } + public string NotAnEqualityComponent { get; } - protected override IEnumerable GetEqualityComponents() - { - yield return A; - yield return B; - yield return C; - yield return D; - } + protected override IEnumerable GetEqualityComponents() + { + yield return A; + yield return B; + yield return C; + yield return D; } + } - private class ValueObjectB : ValueObject + private class ValueObjectB : ValueObject + { + public ValueObjectB(int a, string b, params int[] c) { - public ValueObjectB(int a, string b, params int[] c) - { - A = a; - B = b; - C = c.ToList(); - } + A = a; + B = b; + C = c.ToList(); + } - public int A { get; } - public string B { get; } + public int A { get; } + public string B { get; } - public List C { get; } + public List C { get; } - protected override IEnumerable GetEqualityComponents() - { - yield return A; - yield return B; + protected override IEnumerable GetEqualityComponents() + { + yield return A; + yield return B; - foreach (var c in C) - { - yield return c; - } + foreach (var c in C) + { + yield return c; } } + } - private class ComplexObject : IEquatable + private class ComplexObject : IEquatable + { + public ComplexObject(int a, string b) { - public ComplexObject(int a, string b) - { - A = a; - B = b; - } + A = a; + B = b; + } - public int A { get; set; } + public int A { get; set; } - public string B { get; set; } + public string B { get; set; } - public override bool Equals(object obj) - { - return Equals(obj as ComplexObject); - } + public override bool Equals(object obj) + { + return Equals(obj as ComplexObject); + } - public bool Equals(ComplexObject other) - { - return other != null && - A == other.A && - B == other.B; - } + public bool Equals(ComplexObject other) + { + return other != null && + A == other.A && + B == other.B; + } - public override int GetHashCode() - { - return HashCode.Combine(A, B); - } + public override int GetHashCode() + { + return HashCode.Combine(A, B); } } } diff --git a/src/Services/Ordering/Ordering.UnitTests/GlobalUsings.cs b/src/Services/Ordering/Ordering.UnitTests/GlobalUsings.cs new file mode 100644 index 000000000..9fa77aef7 --- /dev/null +++ b/src/Services/Ordering/Ordering.UnitTests/GlobalUsings.cs @@ -0,0 +1,23 @@ +global using System; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; +global using MediatR; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +global using Microsoft.Extensions.Logging; +global using Moq; +global using System.Collections.Generic; +global using System.Threading.Tasks; +global using Xunit; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +global using System.Threading; +global using global::Ordering.API.Application.IntegrationEvents; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Controllers; +global using System.Linq; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Exceptions; +global using Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; +global using UnitTest.Ordering; diff --git a/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj b/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj index 779c1cc56..6c3cfe2bf 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj +++ b/src/Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj @@ -1,15 +1,15 @@  - net5.0 + net6.0 false false - + - + all diff --git a/src/Services/Payment/Payment.API/Dockerfile b/src/Services/Payment/Payment.API/Dockerfile index d56f3d7c3..e91ed767b 100644 --- a/src/Services/Payment/Payment.API/Dockerfile +++ b/src/Services/Payment/Payment.API/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Payment/Payment.API/Dockerfile.develop b/src/Services/Payment/Payment.API/Dockerfile.develop index bb6e353d2..59ec117f4 100644 --- a/src/Services/Payment/Payment.API/Dockerfile.develop +++ b/src/Services/Payment/Payment.API/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Payment/Payment.API/GlobalUsings.cs b/src/Services/Payment/Payment.API/GlobalUsings.cs new file mode 100644 index 000000000..e87eb53bb --- /dev/null +++ b/src/Services/Payment/Payment.API/GlobalUsings.cs @@ -0,0 +1,29 @@ +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using Azure.Core; +global using Azure.Identity; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore; +global using Azure.Messaging.ServiceBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +global using Microsoft.eShopOnContainers.Payment.API.IntegrationEvents.Events; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Options; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using Microsoft.eShopOnContainers.Payment.API.IntegrationEvents.EventHandling; +global using Microsoft.eShopOnContainers.Payment.API; +global using RabbitMQ.Client; +global using Serilog.Context; +global using Serilog; +global using System.Threading.Tasks; +global using System; +global using System.IO; +global using Microsoft.AspNetCore.Hosting; \ No newline at end of file diff --git a/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs b/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs index 5921529b2..ce9aa4d73 100644 --- a/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs +++ b/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs @@ -1,61 +1,52 @@ -namespace Payment.API.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Payment.API.IntegrationEvents.EventHandling; + +public class OrderStatusChangedToStockConfirmedIntegrationEventHandler : + IIntegrationEventHandler { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; - using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Options; - using Payment.API.IntegrationEvents.Events; - using Serilog.Context; - using System.Threading.Tasks; - - public class OrderStatusChangedToStockConfirmedIntegrationEventHandler : - IIntegrationEventHandler + private readonly IEventBus _eventBus; + private readonly PaymentSettings _settings; + private readonly ILogger _logger; + + public OrderStatusChangedToStockConfirmedIntegrationEventHandler( + IEventBus eventBus, + IOptionsSnapshot settings, + ILogger logger) { - private readonly IEventBus _eventBus; - private readonly PaymentSettings _settings; - private readonly ILogger _logger; - - public OrderStatusChangedToStockConfirmedIntegrationEventHandler( - IEventBus eventBus, - IOptionsSnapshot settings, - ILogger logger) - { - _eventBus = eventBus; - _settings = settings.Value; - _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + _eventBus = eventBus; + _settings = settings.Value; + _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); - _logger.LogTrace("PaymentSettings: {@PaymentSettings}", _settings); - } + _logger.LogTrace("PaymentSettings: {@PaymentSettings}", _settings); + } - public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event) + public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) { - using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) - { - _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); - IntegrationEvent orderPaymentIntegrationEvent; + IntegrationEvent orderPaymentIntegrationEvent; - //Business feature comment: - // When OrderStatusChangedToStockConfirmed Integration Event is handled. - // Here we're simulating that we'd be performing the payment against any payment gateway - // Instead of a real payment we just take the env. var to simulate the payment - // The payment can be successful or it can fail + //Business feature comment: + // When OrderStatusChangedToStockConfirmed Integration Event is handled. + // Here we're simulating that we'd be performing the payment against any payment gateway + // Instead of a real payment we just take the env. var to simulate the payment + // The payment can be successful or it can fail - if (_settings.PaymentSucceeded) - { - orderPaymentIntegrationEvent = new OrderPaymentSucceededIntegrationEvent(@event.OrderId); - } - else - { - orderPaymentIntegrationEvent = new OrderPaymentFailedIntegrationEvent(@event.OrderId); - } + if (_settings.PaymentSucceeded) + { + orderPaymentIntegrationEvent = new OrderPaymentSucceededIntegrationEvent(@event.OrderId); + } + else + { + orderPaymentIntegrationEvent = new OrderPaymentFailedIntegrationEvent(@event.OrderId); + } - _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", orderPaymentIntegrationEvent.Id, Program.AppName, orderPaymentIntegrationEvent); + _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", orderPaymentIntegrationEvent.Id, Program.AppName, orderPaymentIntegrationEvent); - _eventBus.Publish(orderPaymentIntegrationEvent); + _eventBus.Publish(orderPaymentIntegrationEvent); - await Task.CompletedTask; - } + await Task.CompletedTask; } } -} \ No newline at end of file +} diff --git a/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent.cs b/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent.cs index 953e5dbaa..23c713059 100644 --- a/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent.cs +++ b/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent.cs @@ -1,11 +1,8 @@ -namespace Payment.API.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Payment.API.IntegrationEvents.Events; - public record OrderPaymentFailedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderPaymentFailedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId; - } -} \ No newline at end of file + public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs b/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs index 317ef8554..7e6e26600 100644 --- a/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs +++ b/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderPaymentSucceededIntegrationEvent.cs @@ -1,11 +1,8 @@ -namespace Payment.API.IntegrationEvents.Events -{ - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Microsoft.eShopOnContainers.Payment.API.IntegrationEvents.Events; - public record OrderPaymentSucceededIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } +public record OrderPaymentSucceededIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } - public OrderPaymentSucceededIntegrationEvent(int orderId) => OrderId = orderId; - } -} \ No newline at end of file + public OrderPaymentSucceededIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs b/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs index caa3295d5..adac9f2bd 100644 --- a/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs +++ b/src/Services/Payment/Payment.API/IntegrationEvents/Events/OrderStatusChangedToStockConfirmedIntegrationEvent.cs @@ -1,12 +1,9 @@ -namespace Payment.API.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Payment.API.IntegrationEvents.Events; + +public record OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + public int OrderId { get; } - public record OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - - public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId) - => OrderId = orderId; - } -} \ No newline at end of file + public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId) + => OrderId = orderId; +} diff --git a/src/Services/Payment/Payment.API/Payment.API.csproj b/src/Services/Payment/Payment.API/Payment.API.csproj index e438f4e66..ad930772a 100644 --- a/src/Services/Payment/Payment.API/Payment.API.csproj +++ b/src/Services/Payment/Payment.API/Payment.API.csproj @@ -1,12 +1,11 @@  - net5.0 + net6.0 ..\..\..\..\docker-compose.dcproj $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; false - true - preview + true @@ -14,11 +13,12 @@ + + - diff --git a/src/Services/Payment/Payment.API/PaymentSettings.cs b/src/Services/Payment/Payment.API/PaymentSettings.cs index fdb8a29cc..ad2501dec 100644 --- a/src/Services/Payment/Payment.API/PaymentSettings.cs +++ b/src/Services/Payment/Payment.API/PaymentSettings.cs @@ -1,8 +1,8 @@ -namespace Payment.API +namespace Microsoft.eShopOnContainers.Payment.API; + +public class PaymentSettings { - public class PaymentSettings - { - public bool PaymentSucceeded { get; set; } - public string EventBusConnection { get; set; } - } + public bool PaymentSucceeded { get; set; } + public string EventBusConnection { get; set; } } + diff --git a/src/Services/Payment/Payment.API/Program.cs b/src/Services/Payment/Payment.API/Program.cs index 1e5dd1922..6211f5d2f 100644 --- a/src/Services/Payment/Payment.API/Program.cs +++ b/src/Services/Payment/Payment.API/Program.cs @@ -1,15 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Payment.API; -using Serilog; -using System; -using System.IO; - - -var configuration = GetConfiguration(); +var configuration = GetConfiguration(); Log.Logger = CreateSerilogLogger(configuration); @@ -69,16 +58,17 @@ IConfiguration GetConfiguration() if (config.GetValue("UseVault", false)) { - builder.AddAzureKeyVault( - $"https://{config["Vault:Name"]}.vault.azure.net/", + TokenCredential credential = new ClientSecretCredential( + config["Vault:TenantId"], config["Vault:ClientId"], config["Vault:ClientSecret"]); + builder.AddAzureKeyVault(new Uri($"https://{config["Vault:Name"]}.vault.azure.net/"), credential); } return builder.Build(); } -public class Program +public partial class Program { public static string Namespace = typeof(Startup).Namespace; public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); diff --git a/src/Services/Payment/Payment.API/Startup.cs b/src/Services/Payment/Payment.API/Startup.cs index a39d3b97d..c880f2a75 100644 --- a/src/Services/Payment/Payment.API/Startup.cs +++ b/src/Services/Payment/Payment.API/Startup.cs @@ -1,198 +1,178 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.Azure.ServiceBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Logging; -using Payment.API.IntegrationEvents.EventHandling; -using Payment.API.IntegrationEvents.Events; -using RabbitMQ.Client; -using System; - -namespace Payment.API +namespace Microsoft.eShopOnContainers.Payment.API; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the container. - public IServiceProvider ConfigureServices(IServiceCollection services) - { - services.AddCustomHealthCheck(Configuration); - services.Configure(Configuration); + // This method gets called by the runtime. Use this method to add services to the container. + public IServiceProvider ConfigureServices(IServiceCollection services) + { + services.AddCustomHealthCheck(Configuration); + services.Configure(Configuration); - RegisterAppInsights(services); + RegisterAppInsights(services); - if (Configuration.GetValue("AzureServiceBusEnabled")) - { - services.AddSingleton(sp => - { - var serviceBusConnectionString = Configuration["EventBusConnection"]; - var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString); - var subscriptionClientName = Configuration["SubscriptionClientName"]; - - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); - }); - } - else + if (Configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => { - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); - var factory = new ConnectionFactory() - { - HostName = Configuration["EventBusConnection"], - DispatchConsumersAsync = true - }; - - if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) - { - factory.UserName = Configuration["EventBusUserName"]; - } - - if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) - { - factory.Password = Configuration["EventBusPassword"]; - } - - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } - - return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); - }); - } - - RegisterEventBus(services); - - var container = new ContainerBuilder(); - container.Populate(services); - return new AutofacServiceProvider(container.Build()); - } + var serviceBusConnectionString = Configuration["EventBusConnection"]; + var subscriptionClientName = Configuration["SubscriptionClientName"]; - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); + }); + } + else { - //loggerFactory.AddAzureWebAppDiagnostics(); - //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - - var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) + services.AddSingleton(sp => { - app.UsePathBase(pathBase); - } + var logger = sp.GetRequiredService>(); + var factory = new ConnectionFactory() + { + HostName = Configuration["EventBusConnection"], + DispatchConsumersAsync = true + }; - ConfigureEventBus(app); + if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) + { + factory.UserName = Configuration["EventBusUserName"]; + } - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions + factory.Password = Configuration["EventBusPassword"]; + } + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) { - Predicate = r => r.Name.Contains("self") - }); + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); }); } - private void RegisterAppInsights(IServiceCollection services) + RegisterEventBus(services); + + var container = new ContainerBuilder(); + container.Populate(services); + return new AutofacServiceProvider(container.Build()); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + { + //loggerFactory.AddAzureWebAppDiagnostics(); + //loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); + + var pathBase = Configuration["PATH_BASE"]; + if (!string.IsNullOrEmpty(pathBase)) { - services.AddApplicationInsightsTelemetry(Configuration); - services.AddApplicationInsightsKubernetesEnricher(); + app.UsePathBase(pathBase); } - private void RegisterEventBus(IServiceCollection services) + ConfigureEventBus(app); + + app.UseRouting(); + app.UseEndpoints(endpoints => { - if (Configuration.GetValue("AzureServiceBusEnabled")) + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() { - services.AddSingleton(sp => - { - var serviceBusPersisterConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, iLifetimeScope); - }); - } - else + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - services.AddSingleton(sp => - { - var subscriptionClientName = Configuration["SubscriptionClientName"]; - var rabbitMQPersistentConnection = sp.GetRequiredService(); - var iLifetimeScope = sp.GetRequiredService(); - var logger = sp.GetRequiredService>(); - var eventBusSubcriptionsManager = sp.GetRequiredService(); - - var retryCount = 5; - if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) - { - retryCount = int.Parse(Configuration["EventBusRetryCount"]); - } - - return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); - }); - } - - services.AddTransient(); - services.AddSingleton(); - } + Predicate = r => r.Name.Contains("self") + }); + }); + } - private void ConfigureEventBus(IApplicationBuilder app) + private void RegisterAppInsights(IServiceCollection services) + { + services.AddApplicationInsightsTelemetry(Configuration); + services.AddApplicationInsightsKubernetesEnricher(); + } + + private void RegisterEventBus(IServiceCollection services) + { + if (Configuration.GetValue("AzureServiceBusEnabled")) { - var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe(); + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = Configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); + }); } + else + { + services.AddSingleton(sp => + { + var subscriptionClientName = Configuration["SubscriptionClientName"]; + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(Configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } + + services.AddTransient(); + services.AddSingleton(); } - public static class CustomExtensionMethods + private void ConfigureEventBus(IApplicationBuilder app) { - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var hcBuilder = services.AddHealthChecks(); + var eventBus = app.ApplicationServices.GetRequiredService(); + eventBus.Subscribe(); + } +} - hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); +public static class CustomExtensionMethods +{ + public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) + { + var hcBuilder = services.AddHealthChecks(); - if (configuration.GetValue("AzureServiceBusEnabled")) - { - hcBuilder - .AddAzureServiceBusTopic( - configuration["EventBusConnection"], - topicName: "eshop_event_bus", - name: "payment-servicebus-check", - tags: new string[] { "servicebus" }); - } - else - { - hcBuilder - .AddRabbitMQ( - $"amqp://{configuration["EventBusConnection"]}", - name: "payment-rabbitmqbus-check", - tags: new string[] { "rabbitmqbus" }); - } - - return services; + hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); + + if (configuration.GetValue("AzureServiceBusEnabled")) + { + hcBuilder + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "payment-servicebus-check", + tags: new string[] { "servicebus" }); } + else + { + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "payment-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); + } + + return services; } -} \ No newline at end of file +} diff --git a/src/Services/Webhooks/Webhooks.API/Controllers/HomeController.cs b/src/Services/Webhooks/Webhooks.API/Controllers/HomeController.cs index 01c33916f..2a7951ec3 100644 --- a/src/Services/Webhooks/Webhooks.API/Controllers/HomeController.cs +++ b/src/Services/Webhooks/Webhooks.API/Controllers/HomeController.cs @@ -1,15 +1,11 @@ -using Microsoft.AspNetCore.Mvc; +namespace Webhooks.API.Controllers; -namespace Webhooks.API.Controllers +public class HomeController : Controller { - - public class HomeController : Controller + // GET: // + public IActionResult Index() { - // GET: // - public IActionResult Index() - { - return new RedirectResult("~/swagger"); - } - + return new RedirectResult("~/swagger"); } + } diff --git a/src/Services/Webhooks/Webhooks.API/Controllers/WebhookSubscriptionRequest.cs b/src/Services/Webhooks/Webhooks.API/Controllers/WebhookSubscriptionRequest.cs index 2a4fa5cfd..069cd22af 100644 --- a/src/Services/Webhooks/Webhooks.API/Controllers/WebhookSubscriptionRequest.cs +++ b/src/Services/Webhooks/Webhooks.API/Controllers/WebhookSubscriptionRequest.cs @@ -1,35 +1,29 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using Webhooks.API.Model; +namespace Webhooks.API.Controllers; -namespace Webhooks.API.Controllers +public class WebhookSubscriptionRequest : IValidatableObject { - public class WebhookSubscriptionRequest : IValidatableObject - { - public string Url { get; set; } - public string Token { get; set; } - public string Event { get; set; } - public string GrantUrl { get; set; } + public string Url { get; set; } + public string Token { get; set; } + public string Event { get; set; } + public string GrantUrl { get; set; } - public IEnumerable Validate(ValidationContext validationContext) + public IEnumerable Validate(ValidationContext validationContext) + { + if (!Uri.IsWellFormedUriString(GrantUrl, UriKind.Absolute)) { - if (!Uri.IsWellFormedUriString(GrantUrl, UriKind.Absolute)) - { - yield return new ValidationResult("GrantUrl is not valid", new[] { nameof(GrantUrl) }); - } - - if (!Uri.IsWellFormedUriString(Url, UriKind.Absolute)) - { - yield return new ValidationResult("Url is not valid", new[] { nameof(Url) }); - } + yield return new ValidationResult("GrantUrl is not valid", new[] { nameof(GrantUrl) }); + } - var isOk = Enum.TryParse(Event, ignoreCase: true, result: out WebhookType whtype); - if (!isOk) - { - yield return new ValidationResult($"{Event} is invalid event name", new[] { nameof(Event) }); - } + if (!Uri.IsWellFormedUriString(Url, UriKind.Absolute)) + { + yield return new ValidationResult("Url is not valid", new[] { nameof(Url) }); } + var isOk = Enum.TryParse(Event, ignoreCase: true, result: out WebhookType whtype); + if (!isOk) + { + yield return new ValidationResult($"{Event} is invalid event name", new[] { nameof(Event) }); + } } + } diff --git a/src/Services/Webhooks/Webhooks.API/Controllers/WebhooksController.cs b/src/Services/Webhooks/Webhooks.API/Controllers/WebhooksController.cs index 075b220dc..ed5eed705 100644 --- a/src/Services/Webhooks/Webhooks.API/Controllers/WebhooksController.cs +++ b/src/Services/Webhooks/Webhooks.API/Controllers/WebhooksController.cs @@ -1,115 +1,100 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using Webhooks.API.Infrastructure; -using Webhooks.API.Model; -using Webhooks.API.Services; +namespace Webhooks.API.Controllers; -namespace Webhooks.API.Controllers +[Route("api/v1/[controller]")] +[ApiController] +public class WebhooksController : ControllerBase { - [Route("api/v1/[controller]")] - [ApiController] - public class WebhooksController : ControllerBase + private readonly WebhooksContext _dbContext; + private readonly IIdentityService _identityService; + private readonly IGrantUrlTesterService _grantUrlTester; + + public WebhooksController(WebhooksContext dbContext, IIdentityService identityService, IGrantUrlTesterService grantUrlTester) { - private readonly WebhooksContext _dbContext; - private readonly IIdentityService _identityService; - private readonly IGrantUrlTesterService _grantUrlTester; + _dbContext = dbContext; + _identityService = identityService; + _grantUrlTester = grantUrlTester; + } - public WebhooksController(WebhooksContext dbContext, IIdentityService identityService, IGrantUrlTesterService grantUrlTester) - { - _dbContext = dbContext; - _identityService = identityService; - _grantUrlTester = grantUrlTester; - } + [Authorize] + [HttpGet] + [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] + public async Task ListByUser() + { + var userId = _identityService.GetUserIdentity(); + var data = await _dbContext.Subscriptions.Where(s => s.UserId == userId).ToListAsync(); + return Ok(data); + } - [Authorize] - [HttpGet] - [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] - public async Task ListByUser() + [Authorize] + [HttpGet("{id:int}")] + [ProducesResponseType(typeof(WebhookSubscription), (int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task GetByUserAndId(int id) + { + var userId = _identityService.GetUserIdentity(); + var subscription = await _dbContext.Subscriptions.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId); + if (subscription != null) { - var userId = _identityService.GetUserIdentity(); - var data = await _dbContext.Subscriptions.Where(s => s.UserId == userId).ToListAsync(); - return Ok(data); + return Ok(subscription); } + return NotFound($"Subscriptions {id} not found"); + } - [Authorize] - [HttpGet("{id:int}")] - [ProducesResponseType(typeof(WebhookSubscription), (int)HttpStatusCode.OK)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task GetByUserAndId(int id) + [Authorize] + [HttpPost] + [ProducesResponseType((int)HttpStatusCode.Created)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + [ProducesResponseType(418)] + public async Task SubscribeWebhook(WebhookSubscriptionRequest request) + { + if (!ModelState.IsValid) { - var userId = _identityService.GetUserIdentity(); - var subscription = await _dbContext.Subscriptions.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId); - if (subscription != null) - { - return Ok(subscription); - } - return NotFound($"Subscriptions {id} not found"); + return ValidationProblem(ModelState); } - [Authorize] - [HttpPost] - [ProducesResponseType((int)HttpStatusCode.Created)] - [ProducesResponseType((int)HttpStatusCode.BadRequest)] - [ProducesResponseType(418)] - public async Task SubscribeWebhook(WebhookSubscriptionRequest request) - { - if (!ModelState.IsValid) - { - return ValidationProblem(ModelState); - } + var userId = _identityService.GetUserIdentity(); - var userId = _identityService.GetUserIdentity(); + var grantOk = await _grantUrlTester.TestGrantUrl(request.Url, request.GrantUrl, request.Token ?? string.Empty); - var grantOk = await _grantUrlTester.TestGrantUrl(request.Url, request.GrantUrl, request.Token ?? string.Empty); - - if (grantOk) - { - var subscription = new WebhookSubscription() - { - Date = DateTime.UtcNow, - DestUrl = request.Url, - Token = request.Token, - Type = Enum.Parse(request.Event, ignoreCase: true), - UserId = _identityService.GetUserIdentity() - }; - - _dbContext.Add(subscription); - await _dbContext.SaveChangesAsync(); - return CreatedAtAction("GetByUserAndId", new { id = subscription.Id }, subscription); - } - else + if (grantOk) + { + var subscription = new WebhookSubscription() { - return StatusCode(418, "Grant url can't be validated"); - } + Date = DateTime.UtcNow, + DestUrl = request.Url, + Token = request.Token, + Type = Enum.Parse(request.Event, ignoreCase: true), + UserId = _identityService.GetUserIdentity() + }; + + _dbContext.Add(subscription); + await _dbContext.SaveChangesAsync(); + return CreatedAtAction("GetByUserAndId", new { id = subscription.Id }, subscription); } - - [Authorize] - [HttpDelete("{id:int}")] - [ProducesResponseType((int)HttpStatusCode.Accepted)] - [ProducesResponseType((int)HttpStatusCode.NotFound)] - public async Task UnsubscribeWebhook(int id) + else { - var userId = _identityService.GetUserIdentity(); - var subscription = await _dbContext.Subscriptions.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId); + return StatusCode(418, "Grant url can't be validated"); + } + } - if (subscription != null) - { - _dbContext.Remove(subscription); - await _dbContext.SaveChangesAsync(); - return Accepted(); - } + [Authorize] + [HttpDelete("{id:int}")] + [ProducesResponseType((int)HttpStatusCode.Accepted)] + [ProducesResponseType((int)HttpStatusCode.NotFound)] + public async Task UnsubscribeWebhook(int id) + { + var userId = _identityService.GetUserIdentity(); + var subscription = await _dbContext.Subscriptions.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId); - return NotFound($"Subscriptions {id} not found"); + if (subscription != null) + { + _dbContext.Remove(subscription); + await _dbContext.SaveChangesAsync(); + return Accepted(); } + return NotFound($"Subscriptions {id} not found"); } - } diff --git a/src/Services/Webhooks/Webhooks.API/Dockerfile b/src/Services/Webhooks/Webhooks.API/Dockerfile index 263de13d6..b5fb88684 100644 --- a/src/Services/Webhooks/Webhooks.API/Dockerfile +++ b/src/Services/Webhooks/Webhooks.API/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Services/Webhooks/Webhooks.API/Dockerfile.develop b/src/Services/Webhooks/Webhooks.API/Dockerfile.develop index eda18ae91..e981b09f7 100644 --- a/src/Services/Webhooks/Webhooks.API/Dockerfile.develop +++ b/src/Services/Webhooks/Webhooks.API/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:6.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Services/Webhooks/Webhooks.API/Exceptions/WebhooksDomainException.cs b/src/Services/Webhooks/Webhooks.API/Exceptions/WebhooksDomainException.cs index 6307a6296..94f28a525 100644 --- a/src/Services/Webhooks/Webhooks.API/Exceptions/WebhooksDomainException.cs +++ b/src/Services/Webhooks/Webhooks.API/Exceptions/WebhooksDomainException.cs @@ -1,8 +1,5 @@ -using System; +namespace Webhooks.API.Exceptions; -namespace Webhooks.API.Exceptions +public class WebhooksDomainException : Exception { - public class WebhooksDomainException : Exception - { - } } diff --git a/src/Services/Webhooks/Webhooks.API/GlobalUsings.cs b/src/Services/Webhooks/Webhooks.API/GlobalUsings.cs new file mode 100644 index 000000000..c575b7235 --- /dev/null +++ b/src/Services/Webhooks/Webhooks.API/GlobalUsings.cs @@ -0,0 +1,50 @@ +global using Autofac.Extensions.DependencyInjection; +global using Autofac; +global using Devspaces.Support; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc.Filters; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore; +global using Azure.Messaging.ServiceBus; +global using Microsoft.EntityFrameworkCore.Design; +global using Microsoft.EntityFrameworkCore; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.OpenApi.Models; +global using RabbitMQ.Client; +global using Swashbuckle.AspNetCore.SwaggerGen; +global using System.Collections.Generic; +global using System.ComponentModel.DataAnnotations; +global using System.Data.Common; +global using System.IdentityModel.Tokens.Jwt; +global using System.Linq; +global using System.Net.Http; +global using System.Net; +global using System.Reflection; +global using System.Text.Json; +global using System.Text; +global using System.Threading.Tasks; +global using System.Threading; +global using System; +global using Webhooks.API.Exceptions; +global using Webhooks.API.Infrastructure.ActionResult; +global using Webhooks.API.Infrastructure; +global using Webhooks.API.IntegrationEvents; +global using Webhooks.API.Model; +global using Webhooks.API.Services; +global using Webhooks.API; diff --git a/src/Services/Webhooks/Webhooks.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs b/src/Services/Webhooks/Webhooks.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs index 9876cc68b..d71e8b55f 100644 --- a/src/Services/Webhooks/Webhooks.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs +++ b/src/Services/Webhooks/Webhooks.API/Infrastructure/ActionResult/InternalServerErrorObjectResult.cs @@ -1,13 +1,9 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +namespace Webhooks.API.Infrastructure.ActionResult; -namespace Webhooks.API.Infrastructure.ActionResult +class InternalServerErrorObjectResult : ObjectResult { - class InternalServerErrorObjectResult : ObjectResult + public InternalServerErrorObjectResult(object error) : base(error) { - public InternalServerErrorObjectResult(object error) : base(error) - { - StatusCode = StatusCodes.Status500InternalServerError; - } + StatusCode = StatusCodes.Status500InternalServerError; } } diff --git a/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs b/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs index 487a59981..13b0fcbdb 100644 --- a/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs +++ b/src/Services/Webhooks/Webhooks.API/Infrastructure/AuthorizeCheckOperationFilter.cs @@ -1,36 +1,29 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; -using System.Collections.Generic; -using System.Linq; +namespace Webhooks.API.Infrastructure; -namespace Webhooks.API.Infrastructure +public class AuthorizeCheckOperationFilter : IOperationFilter { - public class AuthorizeCheckOperationFilter : IOperationFilter + public void Apply(OpenApiOperation operation, OperationFilterContext context) { - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - // Check for authorize attribute - var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || - context.MethodInfo.GetCustomAttributes(true).OfType().Any(); + // Check for authorize attribute + var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType().Any() || + context.MethodInfo.GetCustomAttributes(true).OfType().Any(); - if (!hasAuthorize) return; + if (!hasAuthorize) return; - operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); - operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); + operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" }); + operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" }); - var oAuthScheme = new OpenApiSecurityScheme - { - Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } - }; + var oAuthScheme = new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } + }; - operation.Security = new List + operation.Security = new List + { + new() { - new OpenApiSecurityRequirement - { - [ oAuthScheme ] = new [] { "webhooksapi" } - } - }; - } + [ oAuthScheme ] = new [] { "webhooksapi" } + } + }; } } diff --git a/src/Services/Webhooks/Webhooks.API/Infrastructure/HttpGlobalExceptionFilter.cs b/src/Services/Webhooks/Webhooks.API/Infrastructure/HttpGlobalExceptionFilter.cs index 7bb818879..a1ebf5c4c 100644 --- a/src/Services/Webhooks/Webhooks.API/Infrastructure/HttpGlobalExceptionFilter.cs +++ b/src/Services/Webhooks/Webhooks.API/Infrastructure/HttpGlobalExceptionFilter.cs @@ -1,69 +1,58 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System.Net; -using Webhooks.API.Exceptions; -using Webhooks.API.Infrastructure.ActionResult; +namespace Webhooks.API.Infrastructure; -namespace Webhooks.API.Infrastructure +public class HttpGlobalExceptionFilter : IExceptionFilter { - public class HttpGlobalExceptionFilter : IExceptionFilter + private readonly IWebHostEnvironment env; + private readonly ILogger logger; + + public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) { - private readonly IWebHostEnvironment env; - private readonly ILogger logger; + this.env = env; + this.logger = logger; + } - public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) - { - this.env = env; - this.logger = logger; - } + public void OnException(ExceptionContext context) + { + logger.LogError(new EventId(context.Exception.HResult), + context.Exception, + context.Exception.Message); - public void OnException(ExceptionContext context) + if (context.Exception.GetType() == typeof(WebhooksDomainException)) { - logger.LogError(new EventId(context.Exception.HResult), - context.Exception, - context.Exception.Message); - - if (context.Exception.GetType() == typeof(WebhooksDomainException)) + var problemDetails = new ValidationProblemDetails() { - var problemDetails = new ValidationProblemDetails() - { - Instance = context.HttpContext.Request.Path, - Status = StatusCodes.Status400BadRequest, - Detail = "Please refer to the errors property for additional details." - }; + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; - problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); + problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); - context.Result = new BadRequestObjectResult(problemDetails); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; - } - else + context.Result = new BadRequestObjectResult(problemDetails); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + } + else + { + var json = new JsonErrorResponse { - var json = new JsonErrorResponse - { - Messages = new[] { "An error ocurred." } - }; - - if (env.IsDevelopment()) - { - json.DeveloperMeesage = context.Exception; - } + Messages = new[] { "An error ocurred." } + }; - context.Result = new InternalServerErrorObjectResult(json); - context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + if (env.IsDevelopment()) + { + json.DeveloperMeesage = context.Exception; } - context.ExceptionHandled = true; + + context.Result = new InternalServerErrorObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; } + context.ExceptionHandled = true; + } - private class JsonErrorResponse - { - public string[] Messages { get; set; } + private class JsonErrorResponse + { + public string[] Messages { get; set; } - public object DeveloperMeesage { get; set; } - } + public object DeveloperMeesage { get; set; } } } diff --git a/src/Services/Webhooks/Webhooks.API/Infrastructure/WebhooksContext.cs b/src/Services/Webhooks/Webhooks.API/Infrastructure/WebhooksContext.cs index f5b9fbf34..b98a27784 100644 --- a/src/Services/Webhooks/Webhooks.API/Infrastructure/WebhooksContext.cs +++ b/src/Services/Webhooks/Webhooks.API/Infrastructure/WebhooksContext.cs @@ -1,26 +1,21 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Webhooks.API.Model; +namespace Webhooks.API.Infrastructure; -namespace Webhooks.API.Infrastructure +public class WebhooksContext : DbContext { - public class WebhooksContext : DbContext - { - public WebhooksContext(DbContextOptions options) : base(options) - { - } - public DbSet Subscriptions { get; set; } + public WebhooksContext(DbContextOptions options) : base(options) + { } + public DbSet Subscriptions { get; set; } +} - public class WebhooksContextDesignFactory : IDesignTimeDbContextFactory +public class WebhooksContextDesignFactory : IDesignTimeDbContextFactory +{ + public WebhooksContext CreateDbContext(string[] args) { - public WebhooksContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder() - .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;Integrated Security=true"); + var optionsBuilder = new DbContextOptionsBuilder() + .UseSqlServer("Server=.;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;Integrated Security=true"); - return new WebhooksContext(optionsBuilder.Options); - } + return new WebhooksContext(optionsBuilder.Options); } } diff --git a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEvent.cs b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEvent.cs index 0f14dd83e..76c458dc0 100644 --- a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEvent.cs +++ b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEvent.cs @@ -1,30 +1,26 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System.Collections.Generic; +namespace Webhooks.API.IntegrationEvents; -namespace Webhooks.API.IntegrationEvents +public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent - { - public int OrderId { get; } - public IEnumerable OrderStockItems { get; } + public int OrderId { get; } + public IEnumerable OrderStockItems { get; } - public OrderStatusChangedToPaidIntegrationEvent(int orderId, - IEnumerable orderStockItems) - { - OrderId = orderId; - OrderStockItems = orderStockItems; - } + public OrderStatusChangedToPaidIntegrationEvent(int orderId, + IEnumerable orderStockItems) + { + OrderId = orderId; + OrderStockItems = orderStockItems; } +} - public record OrderStockItem - { - public int ProductId { get; } - public int Units { get; } +public record OrderStockItem +{ + public int ProductId { get; } + public int Units { get; } - public OrderStockItem(int productId, int units) - { - ProductId = productId; - Units = units; - } + public OrderStockItem(int productId, int units) + { + ProductId = productId; + Units = units; } } diff --git a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEventHandler.cs b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEventHandler.cs index 338ffa7d3..f799fb1c7 100644 --- a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEventHandler.cs +++ b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToPaidIntegrationEventHandler.cs @@ -1,30 +1,22 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; -using Webhooks.API.Model; -using Webhooks.API.Services; +namespace Webhooks.API.IntegrationEvents; -namespace Webhooks.API.IntegrationEvents +public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStatusChangedToPaidIntegrationEventHandler : IIntegrationEventHandler + private readonly IWebhooksRetriever _retriever; + private readonly IWebhooksSender _sender; + private readonly ILogger _logger; + public OrderStatusChangedToPaidIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender, ILogger logger) { - private readonly IWebhooksRetriever _retriever; - private readonly IWebhooksSender _sender; - private readonly ILogger _logger; - public OrderStatusChangedToPaidIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender, ILogger logger) - { - _retriever = retriever; - _sender = sender; - _logger = logger; - } + _retriever = retriever; + _sender = sender; + _logger = logger; + } - public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event) - { - var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderPaid); - _logger.LogInformation("Received OrderStatusChangedToShippedIntegrationEvent and got {SubscriptionsCount} subscriptions to process", subscriptions.Count()); - var whook = new WebhookData(WebhookType.OrderPaid, @event); - await _sender.SendAll(subscriptions, whook); - } + public async Task Handle(OrderStatusChangedToPaidIntegrationEvent @event) + { + var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderPaid); + _logger.LogInformation("Received OrderStatusChangedToShippedIntegrationEvent and got {SubscriptionsCount} subscriptions to process", subscriptions.Count()); + var whook = new WebhookData(WebhookType.OrderPaid, @event); + await _sender.SendAll(subscriptions, whook); } } diff --git a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEvent.cs b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEvent.cs index 2b03abacf..bb20534a6 100644 --- a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEvent.cs +++ b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEvent.cs @@ -1,18 +1,15 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Webhooks.API.IntegrationEvents; -namespace Webhooks.API.IntegrationEvents +public record OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent { - public record OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent - { - public int OrderId { get; private init; } - public string OrderStatus { get; private init; } - public string BuyerName { get; private init; } + public int OrderId { get; private init; } + public string OrderStatus { get; private init; } + public string BuyerName { get; private init; } - public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName) - { - OrderId = orderId; - OrderStatus = orderStatus; - BuyerName = buyerName; - } + public OrderStatusChangedToShippedIntegrationEvent(int orderId, string orderStatus, string buyerName) + { + OrderId = orderId; + OrderStatus = orderStatus; + BuyerName = buyerName; } } diff --git a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEventHandler.cs b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEventHandler.cs index 7f04e2db2..29b21be27 100644 --- a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEventHandler.cs +++ b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/OrderStatusChangedToShippedIntegrationEventHandler.cs @@ -1,30 +1,22 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; -using Webhooks.API.Model; -using Webhooks.API.Services; +namespace Webhooks.API.IntegrationEvents; -namespace Webhooks.API.IntegrationEvents +public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler { - public class OrderStatusChangedToShippedIntegrationEventHandler : IIntegrationEventHandler + private readonly IWebhooksRetriever _retriever; + private readonly IWebhooksSender _sender; + private readonly ILogger _logger; + public OrderStatusChangedToShippedIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender, ILogger logger) { - private readonly IWebhooksRetriever _retriever; - private readonly IWebhooksSender _sender; - private readonly ILogger _logger; - public OrderStatusChangedToShippedIntegrationEventHandler(IWebhooksRetriever retriever, IWebhooksSender sender, ILogger logger) - { - _retriever = retriever; - _sender = sender; - _logger = logger; - } + _retriever = retriever; + _sender = sender; + _logger = logger; + } - public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event) - { - var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderShipped); - _logger.LogInformation("Received OrderStatusChangedToShippedIntegrationEvent and got {SubscriptionCount} subscriptions to process", subscriptions.Count()); - var whook = new WebhookData(WebhookType.OrderShipped, @event); - await _sender.SendAll(subscriptions, whook); - } + public async Task Handle(OrderStatusChangedToShippedIntegrationEvent @event) + { + var subscriptions = await _retriever.GetSubscriptionsOfType(WebhookType.OrderShipped); + _logger.LogInformation("Received OrderStatusChangedToShippedIntegrationEvent and got {SubscriptionCount} subscriptions to process", subscriptions.Count()); + var whook = new WebhookData(WebhookType.OrderShipped, @event); + await _sender.SendAll(subscriptions, whook); } } diff --git a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEvent.cs b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEvent.cs index 8fb860007..0dca66700 100644 --- a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEvent.cs +++ b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEvent.cs @@ -1,20 +1,17 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +namespace Webhooks.API.IntegrationEvents; -namespace Webhooks.API.IntegrationEvents +public record ProductPriceChangedIntegrationEvent : IntegrationEvent { - public record ProductPriceChangedIntegrationEvent : IntegrationEvent - { - public int ProductId { get; private init; } + public int ProductId { get; private init; } - public decimal NewPrice { get; private init; } + public decimal NewPrice { get; private init; } - public decimal OldPrice { get; private init; } + public decimal OldPrice { get; private init; } - public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice) - { - ProductId = productId; - NewPrice = newPrice; - OldPrice = oldPrice; - } + public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice) + { + ProductId = productId; + NewPrice = newPrice; + OldPrice = oldPrice; } } diff --git a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEventHandler.cs b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEventHandler.cs index 044ce3bd3..1172d0820 100644 --- a/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEventHandler.cs +++ b/src/Services/Webhooks/Webhooks.API/IntegrationEvents/ProductPriceChangedIntegrationEventHandler.cs @@ -1,13 +1,9 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using System.Threading.Tasks; +namespace Webhooks.API.IntegrationEvents; -namespace Webhooks.API.IntegrationEvents +public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler { - public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler + public async Task Handle(ProductPriceChangedIntegrationEvent @event) { - public async Task Handle(ProductPriceChangedIntegrationEvent @event) - { - int i = 0; - } + int i = 0; } } diff --git a/src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs b/src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs index 40c2cf2f7..a76a8609d 100644 --- a/src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs +++ b/src/Services/Webhooks/Webhooks.API/Model/WebhookData.cs @@ -1,23 +1,17 @@ -using Newtonsoft.Json; -using System; +namespace Webhooks.API.Model; -namespace Webhooks.API.Model +public class WebhookData { - public class WebhookData - { - public DateTime When { get; } - - public string Payload { get; } + public DateTime When { get; } - public string Type { get; } - - public WebhookData(WebhookType hookType, object data) - { - When = DateTime.UtcNow; - Type = hookType.ToString(); - Payload = JsonConvert.SerializeObject(data); - } + public string Payload { get; } + public string Type { get; } + public WebhookData(WebhookType hookType, object data) + { + When = DateTime.UtcNow; + Type = hookType.ToString(); + Payload = JsonSerializer.Serialize(data); } } diff --git a/src/Services/Webhooks/Webhooks.API/Model/WebhookSubscription.cs b/src/Services/Webhooks/Webhooks.API/Model/WebhookSubscription.cs index 72d726834..1095b5c65 100644 --- a/src/Services/Webhooks/Webhooks.API/Model/WebhookSubscription.cs +++ b/src/Services/Webhooks/Webhooks.API/Model/WebhookSubscription.cs @@ -1,15 +1,12 @@ -using System; +namespace Webhooks.API.Model; -namespace Webhooks.API.Model +public class WebhookSubscription { - public class WebhookSubscription - { - public int Id { get; set; } + public int Id { get; set; } - public WebhookType Type { get; set; } - public DateTime Date { get; set; } - public string DestUrl { get; set; } - public string Token { get; set; } - public string UserId { get; set; } - } + public WebhookType Type { get; set; } + public DateTime Date { get; set; } + public string DestUrl { get; set; } + public string Token { get; set; } + public string UserId { get; set; } } diff --git a/src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs b/src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs index cda3d7316..2e02fc47f 100644 --- a/src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs +++ b/src/Services/Webhooks/Webhooks.API/Model/WebhookType.cs @@ -1,9 +1,8 @@ -namespace Webhooks.API.Model +namespace Webhooks.API.Model; + +public enum WebhookType { - public enum WebhookType - { - CatalogItemPriceChange = 1, - OrderShipped = 2, - OrderPaid = 3 - } + CatalogItemPriceChange = 1, + OrderShipped = 2, + OrderPaid = 3 } diff --git a/src/Services/Webhooks/Webhooks.API/Program.cs b/src/Services/Webhooks/Webhooks.API/Program.cs index 85ab12997..027814057 100644 --- a/src/Services/Webhooks/Webhooks.API/Program.cs +++ b/src/Services/Webhooks/Webhooks.API/Program.cs @@ -1,11 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Webhooks.API; -using Webhooks.API.Infrastructure; - -CreateWebHostBuilder(args).Build() +CreateWebHostBuilder(args).Build() .MigrateDbContext((_, __) => { }) .Run(); diff --git a/src/Services/Webhooks/Webhooks.API/Services/GrantUrlTesterService.cs b/src/Services/Webhooks/Webhooks.API/Services/GrantUrlTesterService.cs index fef390dda..ea75ac343 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/GrantUrlTesterService.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/GrantUrlTesterService.cs @@ -1,57 +1,50 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +class GrantUrlTesterService : IGrantUrlTesterService { - class GrantUrlTesterService : IGrantUrlTesterService + private readonly IHttpClientFactory _clientFactory; + private readonly ILogger _logger; + public GrantUrlTesterService(IHttpClientFactory factory, ILogger logger) { - private readonly IHttpClientFactory _clientFactory; - private readonly ILogger _logger; - public GrantUrlTesterService(IHttpClientFactory factory, ILogger logger) - { - _clientFactory = factory; - _logger = logger; - } + _clientFactory = factory; + _logger = logger; + } - public async Task TestGrantUrl(string urlHook, string url, string token) + public async Task TestGrantUrl(string urlHook, string url, string token) + { + if (!CheckSameOrigin(urlHook, url)) { - if (!CheckSameOrigin(urlHook, url)) - { - _logger.LogWarning("Url of the hook ({UrlHook} and the grant url ({Url} do not belong to same origin)", urlHook, url); - return false; - } + _logger.LogWarning("Url of the hook ({UrlHook} and the grant url ({Url} do not belong to same origin)", urlHook, url); + return false; + } - var client = _clientFactory.CreateClient("GrantClient"); - var msg = new HttpRequestMessage(HttpMethod.Options, url); - msg.Headers.Add("X-eshop-whtoken", token); - _logger.LogInformation("Sending the OPTIONS message to {Url} with token \"{Token}\"", url, token ?? string.Empty); - try - { - var response = await client.SendAsync(msg); - var tokenReceived = response.Headers.TryGetValues("X-eshop-whtoken", out var tokenValues) ? tokenValues.FirstOrDefault() : null; - var tokenExpected = string.IsNullOrWhiteSpace(token) ? null : token; - _logger.LogInformation("Response code is {StatusCode} for url {Url} and token in header was {TokenReceived} (expected token was {TokenExpected})", response.StatusCode, url, tokenReceived, tokenExpected); - return response.IsSuccessStatusCode && tokenReceived == tokenExpected; - } - catch (Exception ex) - { - _logger.LogWarning("Exception {TypeName} when sending OPTIONS request. Url can't be granted.", ex.GetType().Name); - return false; - } + var client = _clientFactory.CreateClient("GrantClient"); + var msg = new HttpRequestMessage(HttpMethod.Options, url); + msg.Headers.Add("X-eshop-whtoken", token); + _logger.LogInformation("Sending the OPTIONS message to {Url} with token \"{Token}\"", url, token ?? string.Empty); + try + { + var response = await client.SendAsync(msg); + var tokenReceived = response.Headers.TryGetValues("X-eshop-whtoken", out var tokenValues) ? tokenValues.FirstOrDefault() : null; + var tokenExpected = string.IsNullOrWhiteSpace(token) ? null : token; + _logger.LogInformation("Response code is {StatusCode} for url {Url} and token in header was {TokenReceived} (expected token was {TokenExpected})", response.StatusCode, url, tokenReceived, tokenExpected); + return response.IsSuccessStatusCode && tokenReceived == tokenExpected; } - - private bool CheckSameOrigin(string urlHook, string url) + catch (Exception ex) { - var firstUrl = new Uri(urlHook, UriKind.Absolute); - var secondUrl = new Uri(url, UriKind.Absolute); - - return firstUrl.Scheme == secondUrl.Scheme && - firstUrl.Port == secondUrl.Port && - firstUrl.Host == firstUrl.Host; + _logger.LogWarning("Exception {TypeName} when sending OPTIONS request. Url can't be granted.", ex.GetType().Name); + return false; } } + + private bool CheckSameOrigin(string urlHook, string url) + { + var firstUrl = new Uri(urlHook, UriKind.Absolute); + var secondUrl = new Uri(url, UriKind.Absolute); + + return firstUrl.Scheme == secondUrl.Scheme && + firstUrl.Port == secondUrl.Port && + firstUrl.Host == firstUrl.Host; + } } diff --git a/src/Services/Webhooks/Webhooks.API/Services/IGrantUrlTesterService.cs b/src/Services/Webhooks/Webhooks.API/Services/IGrantUrlTesterService.cs index c69e41934..c4ccf764f 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/IGrantUrlTesterService.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/IGrantUrlTesterService.cs @@ -1,9 +1,6 @@ -using System.Threading.Tasks; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +public interface IGrantUrlTesterService { - public interface IGrantUrlTesterService - { - Task TestGrantUrl(string urlHook, string url, string token); - } + Task TestGrantUrl(string urlHook, string url, string token); } diff --git a/src/Services/Webhooks/Webhooks.API/Services/IIdentityService.cs b/src/Services/Webhooks/Webhooks.API/Services/IIdentityService.cs index 678ae1b97..97d2a0b67 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/IIdentityService.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/IIdentityService.cs @@ -1,7 +1,6 @@ -namespace Webhooks.API.Services +namespace Webhooks.API.Services; + +public interface IIdentityService { - public interface IIdentityService - { - string GetUserIdentity(); - } + string GetUserIdentity(); } diff --git a/src/Services/Webhooks/Webhooks.API/Services/IWebhooksRetriever.cs b/src/Services/Webhooks/Webhooks.API/Services/IWebhooksRetriever.cs index 0ae20f03b..20e6439b6 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/IWebhooksRetriever.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/IWebhooksRetriever.cs @@ -1,12 +1,7 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Webhooks.API.Model; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +public interface IWebhooksRetriever { - public interface IWebhooksRetriever - { - Task> GetSubscriptionsOfType(WebhookType type); - } + Task> GetSubscriptionsOfType(WebhookType type); } diff --git a/src/Services/Webhooks/Webhooks.API/Services/IWebhooksSender.cs b/src/Services/Webhooks/Webhooks.API/Services/IWebhooksSender.cs index a0a412ef8..2bfb4955d 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/IWebhooksSender.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/IWebhooksSender.cs @@ -1,11 +1,6 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Webhooks.API.Model; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +public interface IWebhooksSender { - public interface IWebhooksSender - { - Task SendAll(IEnumerable receivers, WebhookData data); - } + Task SendAll(IEnumerable receivers, WebhookData data); } diff --git a/src/Services/Webhooks/Webhooks.API/Services/IdentityService.cs b/src/Services/Webhooks/Webhooks.API/Services/IdentityService.cs index be1d54570..cd821dc74 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/IdentityService.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/IdentityService.cs @@ -1,21 +1,16 @@ - -using Microsoft.AspNetCore.Http; -using System; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +public class IdentityService : IIdentityService { - public class IdentityService : IIdentityService - { - private IHttpContextAccessor _context; + private IHttpContextAccessor _context; - public IdentityService(IHttpContextAccessor context) - { - _context = context ?? throw new ArgumentNullException(nameof(context)); - } + public IdentityService(IHttpContextAccessor context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } - public string GetUserIdentity() - { - return _context.HttpContext.User.FindFirst("sub").Value; - } + public string GetUserIdentity() + { + return _context.HttpContext.User.FindFirst("sub").Value; } } diff --git a/src/Services/Webhooks/Webhooks.API/Services/WebhooksRetriever.cs b/src/Services/Webhooks/Webhooks.API/Services/WebhooksRetriever.cs index 1f7fb3f1c..d34ddc5a0 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/WebhooksRetriever.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/WebhooksRetriever.cs @@ -1,23 +1,15 @@ -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Webhooks.API.Infrastructure; -using Webhooks.API.Model; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +public class WebhooksRetriever : IWebhooksRetriever { - public class WebhooksRetriever : IWebhooksRetriever + private readonly WebhooksContext _db; + public WebhooksRetriever(WebhooksContext db) { - private readonly WebhooksContext _db; - public WebhooksRetriever(WebhooksContext db) - { - _db = db; - } - public async Task> GetSubscriptionsOfType(WebhookType type) - { - var data = await _db.Subscriptions.Where(s => s.Type == type).ToListAsync(); - return data; - } + _db = db; + } + public async Task> GetSubscriptionsOfType(WebhookType type) + { + var data = await _db.Subscriptions.Where(s => s.Type == type).ToListAsync(); + return data; } } diff --git a/src/Services/Webhooks/Webhooks.API/Services/WebhooksSender.cs b/src/Services/Webhooks/Webhooks.API/Services/WebhooksSender.cs index 7ab7a0c67..625662a93 100644 --- a/src/Services/Webhooks/Webhooks.API/Services/WebhooksSender.cs +++ b/src/Services/Webhooks/Webhooks.API/Services/WebhooksSender.cs @@ -1,49 +1,38 @@ -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Webhooks.API.Model; +namespace Webhooks.API.Services; -namespace Webhooks.API.Services +public class WebhooksSender : IWebhooksSender { - public class WebhooksSender : IWebhooksSender + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILogger _logger; + public WebhooksSender(IHttpClientFactory httpClientFactory, ILogger logger) { - private readonly IHttpClientFactory _httpClientFactory; - private readonly ILogger _logger; - public WebhooksSender(IHttpClientFactory httpClientFactory, ILogger logger) - { - _httpClientFactory = httpClientFactory; - _logger = logger; - } + _httpClientFactory = httpClientFactory; + _logger = logger; + } - public async Task SendAll(IEnumerable receivers, WebhookData data) - { - var client = _httpClientFactory.CreateClient(); - var json = JsonConvert.SerializeObject(data); - var tasks = receivers.Select(r => OnSendData(r, json, client)); - await Task.WhenAll(tasks.ToArray()); - } + public async Task SendAll(IEnumerable receivers, WebhookData data) + { + var client = _httpClientFactory.CreateClient(); + var json = JsonSerializer.Serialize(data); + var tasks = receivers.Select(r => OnSendData(r, json, client)); + await Task.WhenAll(tasks.ToArray()); + } - private Task OnSendData(WebhookSubscription subs, string jsonData, HttpClient client) + private Task OnSendData(WebhookSubscription subs, string jsonData, HttpClient client) + { + var request = new HttpRequestMessage() { - var request = new HttpRequestMessage() - { - RequestUri = new Uri(subs.DestUrl, UriKind.Absolute), - Method = HttpMethod.Post, - Content = new StringContent(jsonData, Encoding.UTF8, "application/json") - }; + RequestUri = new Uri(subs.DestUrl, UriKind.Absolute), + Method = HttpMethod.Post, + Content = new StringContent(jsonData, Encoding.UTF8, "application/json") + }; - if (!string.IsNullOrWhiteSpace(subs.Token)) - { - request.Headers.Add("X-eshop-whtoken", subs.Token); - } - _logger.LogDebug("Sending hook to {DestUrl} of type {Type}", subs.Type.ToString(), subs.Type.ToString()); - return client.SendAsync(request); + if (!string.IsNullOrWhiteSpace(subs.Token)) + { + request.Headers.Add("X-eshop-whtoken", subs.Token); } - + _logger.LogDebug("Sending hook to {DestUrl} of type {Type}", subs.Type.ToString(), subs.Type.ToString()); + return client.SendAsync(request); } + } diff --git a/src/Services/Webhooks/Webhooks.API/Startup.cs b/src/Services/Webhooks/Webhooks.API/Startup.cs index 4744e9d24..256941efa 100644 --- a/src/Services/Webhooks/Webhooks.API/Startup.cs +++ b/src/Services/Webhooks/Webhooks.API/Startup.cs @@ -1,213 +1,176 @@ -using Autofac; -using Autofac.Extensions.DependencyInjection; -using Devspaces.Support; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Http; -using Microsoft.Azure.ServiceBus; -using Microsoft.EntityFrameworkCore; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; -using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; -using RabbitMQ.Client; -using System; -using System.Collections.Generic; -using System.Data.Common; -using System.IdentityModel.Tokens.Jwt; -using System.Reflection; -using System.Threading; -using Webhooks.API.Infrastructure; -using Webhooks.API.IntegrationEvents; -using Webhooks.API.Services; - -namespace Webhooks.API +namespace Webhooks.API; +public class Startup { - public class Startup + public IConfiguration Configuration { get; } + + public Startup(IConfiguration configuration) { - public IConfiguration Configuration { get; } + Configuration = configuration; + } - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + public IServiceProvider ConfigureServices(IServiceCollection services) + { + services + .AddAppInsight(Configuration) + .AddCustomRouting(Configuration) + .AddCustomDbContext(Configuration) + .AddSwagger(Configuration) + .AddCustomHealthCheck(Configuration) + .AddDevspaces() + .AddHttpClientServices(Configuration) + .AddIntegrationServices(Configuration) + .AddEventBus(Configuration) + .AddCustomAuthentication(Configuration) + .AddSingleton() + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient(); + + var container = new ContainerBuilder(); + container.Populate(services); + return new AutofacServiceProvider(container.Build()); + } + + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) + { + var pathBase = Configuration["PATH_BASE"]; - public IServiceProvider ConfigureServices(IServiceCollection services) + if (!string.IsNullOrEmpty(pathBase)) { - services - .AddAppInsight(Configuration) - .AddCustomRouting(Configuration) - .AddCustomDbContext(Configuration) - .AddSwagger(Configuration) - .AddCustomHealthCheck(Configuration) - .AddDevspaces() - .AddHttpClientServices(Configuration) - .AddIntegrationServices(Configuration) - .AddEventBus(Configuration) - .AddCustomAuthentication(Configuration) - .AddSingleton() - .AddTransient() - .AddTransient() - .AddTransient() - .AddTransient(); - - var container = new ContainerBuilder(); - container.Populate(services); - return new AutofacServiceProvider(container.Build()); + loggerFactory.CreateLogger("init").LogDebug("Using PATH BASE '{PathBase}'", pathBase); + app.UsePathBase(pathBase); } - public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) - { - loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); - - var pathBase = Configuration["PATH_BASE"]; + app.UseRouting(); + app.UseCors("CorsPolicy"); + ConfigureAuth(app); - if (!string.IsNullOrEmpty(pathBase)) + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + endpoints.MapControllers(); + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() { - loggerFactory.CreateLogger("init").LogDebug("Using PATH BASE '{PathBase}'", pathBase); - app.UsePathBase(pathBase); - } - - - - app.UseRouting(); - app.UseCors("CorsPolicy"); - ConfigureAuth(app); - - app.UseEndpoints(endpoints => + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); + Predicate = r => r.Name.Contains("self") }); + }); - app.UseSwagger() - .UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Webhooks.API V1"); - c.OAuthClientId("webhooksswaggerui"); - c.OAuthAppName("WebHooks Service Swagger UI"); - }); + app.UseSwagger() + .UseSwaggerUI(c => + { + c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Webhooks.API V1"); + c.OAuthClientId("webhooksswaggerui"); + c.OAuthAppName("WebHooks Service Swagger UI"); + }); - ConfigureEventBus(app); - } + ConfigureEventBus(app); + } - protected virtual void ConfigureAuth(IApplicationBuilder app) - { - app.UseAuthentication(); - app.UseAuthorization(); - } + protected virtual void ConfigureAuth(IApplicationBuilder app) + { + app.UseAuthentication(); + app.UseAuthorization(); + } - protected virtual void ConfigureEventBus(IApplicationBuilder app) - { - var eventBus = app.ApplicationServices.GetRequiredService(); - eventBus.Subscribe(); - eventBus.Subscribe(); - eventBus.Subscribe(); - } + protected virtual void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + eventBus.Subscribe(); + eventBus.Subscribe(); + eventBus.Subscribe(); } +} - static class CustomExtensionMethods +static class CustomExtensionMethods +{ + public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) { - public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) - { - services.AddApplicationInsightsTelemetry(configuration); - services.AddApplicationInsightsKubernetesEnricher(); + services.AddApplicationInsightsTelemetry(configuration); + services.AddApplicationInsightsKubernetesEnricher(); - return services; - } + return services; + } - public static IServiceCollection AddCustomRouting(this IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddCustomRouting(this IServiceCollection services, IConfiguration configuration) + { + services.AddControllers(options => { - services.AddControllers(options => - { - options.Filters.Add(typeof(HttpGlobalExceptionFilter)); - }); + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + }); - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder - .SetIsOriginAllowed((host) => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials()); - }); - - return services; - } + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } - public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) + { + services.AddEntityFrameworkSqlServer() + .AddDbContext(options => { - services.AddEntityFrameworkSqlServer() - .AddDbContext(options => + options.UseSqlServer(configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + }); + + return services; + } + + public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) + { + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { - options.UseSqlServer(configuration["ConnectionString"], - sqlServerOptionsAction: sqlOptions => - { - sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); - //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency - sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); - }); + Title = "eShopOnContainers - Webhooks HTTP API", + Version = "v1", + Description = "The Webhooks Microservice HTTP API. This is a simple webhooks CRUD registration entrypoint" }); - return services; - } - - public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) - { - services.AddSwaggerGen(options => + options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { - options.DescribeAllEnumsAsStrings(); - options.SwaggerDoc("v1", new OpenApiInfo - { - Title = "eShopOnContainers - Webhooks HTTP API", - Version = "v1", - Description = "The Webhooks Microservice HTTP API. This is a simple webhooks CRUD registration entrypoint" - }); - - options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() + Implicit = new OpenApiOAuthFlow() { - Implicit = new OpenApiOAuthFlow() + AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), + TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), + Scopes = new Dictionary() { - AuthorizationUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/authorize"), - TokenUrl = new Uri($"{configuration.GetValue("IdentityUrlExternal")}/connect/token"), - Scopes = new Dictionary() - { - { "webhooks", "Webhooks API" } - } + { "webhooks", "Webhooks API" } } } - }); - - options.OperationFilter(); + } }); - return services; - } - public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) - { - if (configuration.GetValue("AzureServiceBusEnabled")) + options.OperationFilter(); + }); + + return services; + } + public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + { + if (configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { @@ -215,9 +178,10 @@ namespace Webhooks.API var iLifetimeScope = sp.GetRequiredService(); var logger = sp.GetRequiredService>(); var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = configuration["SubscriptionClientName"]; return new EventBusServiceBus(serviceBusPersisterConnection, logger, - eventBusSubcriptionsManager, iLifetimeScope); + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); }); } @@ -245,49 +209,49 @@ namespace Webhooks.API services.AddTransient(); services.AddTransient(); services.AddTransient(); + return services; - } + } - public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) - { - var accountName = configuration.GetValue("AzureStorageAccountName"); - var accountKey = configuration.GetValue("AzureStorageAccountKey"); + public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) + { + var accountName = configuration.GetValue("AzureStorageAccountName"); + var accountKey = configuration.GetValue("AzureStorageAccountKey"); - var hcBuilder = services.AddHealthChecks(); + var hcBuilder = services.AddHealthChecks(); - hcBuilder - .AddCheck("self", () => HealthCheckResult.Healthy()) - .AddSqlServer( - configuration["ConnectionString"], - name: "WebhooksApiDb-check", - tags: new string[] { "webhooksdb" }); + hcBuilder + .AddCheck("self", () => HealthCheckResult.Healthy()) + .AddSqlServer( + configuration["ConnectionString"], + name: "WebhooksApiDb-check", + tags: new string[] { "webhooksdb" }); - return services; - } + return services; + } - public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); - services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan); - //add http client services - services.AddHttpClient("GrantClient") - .SetHandlerLifetime(TimeSpan.FromMinutes(5)) - .AddDevspacesSupport(); - return services; - } + public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(); + services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan); + //add http client services + services.AddHttpClient("GrantClient") + .SetHandlerLifetime(TimeSpan.FromMinutes(5)) + .AddDevspacesSupport(); + return services; + } - public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) - { - services.AddTransient>( + public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) + { + services.AddTransient>( sp => (DbConnection c) => new IntegrationEventLogService(c)); if (configuration.GetValue("AzureServiceBusEnabled")) { services.AddSingleton(sp => { - var serviceBusConnection = new ServiceBusConnectionStringBuilder(configuration["EventBusConnection"]); var subscriptionClientName = configuration["SubscriptionClientName"]; - return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName); + return new DefaultServiceBusPersisterConnection(configuration["EventBusConnection"]); }); } else @@ -323,28 +287,27 @@ namespace Webhooks.API } return services; - } + } - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) - { - // prevent from mapping "sub" claim to nameidentifier. - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + // prevent from mapping "sub" claim to nameidentifier. + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - var identityUrl = configuration.GetValue("IdentityUrl"); + var identityUrl = configuration.GetValue("IdentityUrl"); - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + services.AddAuthentication(options => + { + options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(options => - { - options.Authority = identityUrl; - options.RequireHttpsMetadata = false; - options.Audience = "webhooks"; - }); + }).AddJwtBearer(options => + { + options.Authority = identityUrl; + options.RequireHttpsMetadata = false; + options.Audience = "webhooks"; + }); - return services; - } + return services; } -} \ No newline at end of file +} diff --git a/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj b/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj index b26e28b6a..c05884309 100644 --- a/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj +++ b/src/Services/Webhooks/Webhooks.API/Webhooks.API.csproj @@ -1,13 +1,12 @@  - net5.0 + net6.0 InProcess Linux $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; false - true - preview + true @@ -17,7 +16,7 @@ - + diff --git a/src/Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj b/src/Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj index ed719bc26..c8be1e5f8 100644 --- a/src/Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj +++ b/src/Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 true false false diff --git a/src/Tests/Services/Application.FunctionalTests/Extensions/HttpClientExtensions.cs b/src/Tests/Services/Application.FunctionalTests/Extensions/HttpClientExtensions.cs index 25475462d..b17edce91 100644 --- a/src/Tests/Services/Application.FunctionalTests/Extensions/HttpClientExtensions.cs +++ b/src/Tests/Services/Application.FunctionalTests/Extensions/HttpClientExtensions.cs @@ -1,16 +1,11 @@ -using Microsoft.AspNetCore.TestHost; -using System; -using System.Net.Http; +namespace FunctionalTests.Extensions; -namespace FunctionalTests.Extensions +static class HttpClientExtensions { - static class HttpClientExtensions + public static HttpClient CreateIdempotentClient(this TestServer server) { - public static HttpClient CreateIdempotentClient(this TestServer server) - { - var client = server.CreateClient(); - client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); - return client; - } + var client = server.CreateClient(); + client.DefaultRequestHeaders.Add("x-requestid", Guid.NewGuid().ToString()); + return client; } } diff --git a/src/Tests/Services/Application.FunctionalTests/GlobalUsings.cs b/src/Tests/Services/Application.FunctionalTests/GlobalUsings.cs new file mode 100644 index 000000000..5bacd265b --- /dev/null +++ b/src/Tests/Services/Application.FunctionalTests/GlobalUsings.cs @@ -0,0 +1,35 @@ +global using Microsoft.AspNetCore.TestHost; +global using System; +global using System.Net.Http; +global using Microsoft.AspNetCore.Http; +global using System.Security.Claims; +global using System.Threading.Tasks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.Extensions.Configuration; +global using System.IO; +global using System.Reflection; +global using FunctionalTests.Middleware; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.eShopOnContainers.Services.Basket.API; +global using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +global using Microsoft.eShopOnContainers.Services.Catalog.API; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using FunctionalTests.Extensions; +global using FunctionalTests.Services.Basket; +global using Microsoft.eShopOnContainers.Services.Basket.API.Model; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels; +global using System.Text.Json; +global using System.Collections.Generic; +global using System.Linq; +global using System.Text; +global using WebMVC.Services.ModelDTOs; +global using Xunit; +global using Microsoft.eShopOnContainers.Services.Ordering.API; +global using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; +global using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; +global using FunctionalTests.Services.Catalog; +global using Microsoft.eShopOnContainers.Services.Catalog.API.Model; +global using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel; \ No newline at end of file diff --git a/src/Tests/Services/Application.FunctionalTests/Middleware/AutoAuthorizeMiddleware.cs b/src/Tests/Services/Application.FunctionalTests/Middleware/AutoAuthorizeMiddleware.cs index d78dcc80d..40c3c2ad8 100644 --- a/src/Tests/Services/Application.FunctionalTests/Middleware/AutoAuthorizeMiddleware.cs +++ b/src/Tests/Services/Application.FunctionalTests/Middleware/AutoAuthorizeMiddleware.cs @@ -1,31 +1,26 @@ -using Microsoft.AspNetCore.Http; -using System.Security.Claims; -using System.Threading.Tasks; +namespace FunctionalTests.Middleware; -namespace FunctionalTests.Middleware +class AutoAuthorizeMiddleware { - class AutoAuthorizeMiddleware - { - public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"; + public const string IDENTITY_ID = "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"; - private readonly RequestDelegate _next; + private readonly RequestDelegate _next; - public AutoAuthorizeMiddleware(RequestDelegate rd) - { - _next = rd; - } + public AutoAuthorizeMiddleware(RequestDelegate rd) + { + _next = rd; + } - public async Task Invoke(HttpContext httpContext) - { - var identity = new ClaimsIdentity("cookies"); + public async Task Invoke(HttpContext httpContext) + { + var identity = new ClaimsIdentity("cookies"); - identity.AddClaim(new Claim("sub", IDENTITY_ID)); - identity.AddClaim(new Claim("unique_name", IDENTITY_ID)); - identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID)); + identity.AddClaim(new Claim("sub", IDENTITY_ID)); + identity.AddClaim(new Claim("unique_name", IDENTITY_ID)); + identity.AddClaim(new Claim(ClaimTypes.Name, IDENTITY_ID)); - httpContext.User.AddIdentity(identity); - await _next.Invoke(httpContext); - } + httpContext.User.AddIdentity(identity); + await _next.Invoke(httpContext); } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketScenariosBase.cs b/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketScenariosBase.cs index a447d2922..71487d7b4 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketScenariosBase.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketScenariosBase.cs @@ -1,49 +1,42 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.Configuration; -using System.IO; -using System.Reflection; +namespace FunctionalTests.Services.Basket; -namespace FunctionalTests.Services.Basket +public class BasketScenariosBase { - public class BasketScenariosBase - { - private const string ApiUrlBase = "api/v1/basket"; + private const string ApiUrlBase = "api/v1/basket"; - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(BasketScenariosBase)) - .Location; - - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("Services/Basket/appsettings.json", optional: false) - .AddEnvironmentVariables(); - }).UseStartup(); - - return new TestServer(hostBuilder); - } + public TestServer CreateServer() + { + var path = Assembly.GetAssembly(typeof(BasketScenariosBase)) + .Location; - public static class Get - { - public static string GetBasket(int id) + var hostBuilder = new WebHostBuilder() + .UseContentRoot(Path.GetDirectoryName(path)) + .ConfigureAppConfiguration(cb => { - return $"{ApiUrlBase}/{id}"; - } + cb.AddJsonFile("Services/Basket/appsettings.json", optional: false) + .AddEnvironmentVariables(); + }).UseStartup(); - public static string GetBasketByCustomer(string customerId) - { - return $"{ApiUrlBase}/{customerId}"; - } + return new TestServer(hostBuilder); + } + + public static class Get + { + public static string GetBasket(int id) + { + return $"{ApiUrlBase}/{id}"; } - public static class Post + public static string GetBasketByCustomer(string customerId) { - public static string CreateBasket = $"{ApiUrlBase}/"; - public static string CheckoutOrder = $"{ApiUrlBase}/checkout"; + return $"{ApiUrlBase}/{customerId}"; } } + + public static class Post + { + public static string CreateBasket = $"{ApiUrlBase}/"; + public static string CheckoutOrder = $"{ApiUrlBase}/checkout"; + } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketTestsStartup.cs b/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketTestsStartup.cs index 6043a7ab3..23523a9f4 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketTestsStartup.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Basket/BasketTestsStartup.cs @@ -1,27 +1,21 @@ -using FunctionalTests.Middleware; -using Microsoft.AspNetCore.Builder; +namespace FunctionalTests.Services.Basket; using Microsoft.eShopOnContainers.Services.Basket.API; -using Microsoft.Extensions.Configuration; - -namespace FunctionalTests.Services.Basket +class BasketTestsStartup : Startup { - class BasketTestsStartup : Startup + public BasketTestsStartup(IConfiguration env) : base(env) { - public BasketTestsStartup(IConfiguration env) : base(env) + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) { + app.UseMiddleware(); + app.UseAuthorization(); } - - protected override void ConfigureAuth(IApplicationBuilder app) + else { - if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) - { - app.UseMiddleware(); - app.UseAuthorization(); - } - else - { - base.ConfigureAuth(app); - } + base.ConfigureAuth(app); } } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Catalog/CatalogScenariosBase.cs b/src/Tests/Services/Application.FunctionalTests/Services/Catalog/CatalogScenariosBase.cs index c5d9ab72d..ec762a947 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Catalog/CatalogScenariosBase.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Catalog/CatalogScenariosBase.cs @@ -1,65 +1,53 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; +namespace FunctionalTests.Services.Catalog; using Microsoft.eShopOnContainers.Services.Catalog.API; -using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.IO; -using System.Reflection; -namespace FunctionalTests.Services.Catalog +public class CatalogScenariosBase { - public class CatalogScenariosBase + public TestServer CreateServer() { - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(CatalogScenariosBase)) - .Location; + var path = Assembly.GetAssembly(typeof(CatalogScenariosBase)) + .Location; - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("Services/Catalog/appsettings.json", optional: false) - .AddEnvironmentVariables(); - }).UseStartup(); + var hostBuilder = new WebHostBuilder() + .UseContentRoot(Path.GetDirectoryName(path)) + .ConfigureAppConfiguration(cb => + { + cb.AddJsonFile("Services/Catalog/appsettings.json", optional: false) + .AddEnvironmentVariables(); + }).UseStartup(); - var testServer = new TestServer(hostBuilder); + var testServer = new TestServer(hostBuilder); - testServer.Host - .MigrateDbContext((context, services) => - { - var env = services.GetService(); - var settings = services.GetService>(); - var logger = services.GetService>(); + testServer.Host + .MigrateDbContext((context, services) => + { + var env = services.GetService(); + var settings = services.GetService>(); + var logger = services.GetService>(); - new CatalogContextSeed() - .SeedAsync(context, env, settings, logger) - .Wait(); - }) - .MigrateDbContext((_, __) => { }); + new CatalogContextSeed() + .SeedAsync(context, env, settings, logger) + .Wait(); + }) + .MigrateDbContext((_, __) => { }); - return testServer; - } - - public static class Get - { - public static string Orders = "api/v1/orders"; + return testServer; + } - public static string Items = "api/v1/catalog/items"; + public static class Get + { + public static string Orders = "api/v1/orders"; - public static string ProductByName(string name) - { - return $"api/v1/catalog/items/withname/{name}"; - } - } + public static string Items = "api/v1/catalog/items"; - public static class Put + public static string ProductByName(string name) { - public static string UpdateCatalogProduct = "api/v1/catalog/items"; + return $"api/v1/catalog/items/withname/{name}"; } } + + public static class Put + { + public static string UpdateCatalogProduct = "api/v1/catalog/items"; + } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs b/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs index a8bdcd122..86466766f 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/IntegrationEventsScenarios.cs @@ -1,128 +1,120 @@ -using FunctionalTests.Services.Basket; -using FunctionalTests.Services.Catalog; +namespace FunctionalTests.Services; using Microsoft.eShopOnContainers.Services.Basket.API.Model; using Microsoft.eShopOnContainers.Services.Catalog.API.Model; using Microsoft.eShopOnContainers.Services.Catalog.API.ViewModel; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace FunctionalTests.Services + +public class IntegrationEventsScenarios { - public class IntegrationEventsScenarios + [Fact] + public async Task Post_update_product_price_and_catalog_and_basket_list_modified() { - [Fact] - public async Task Post_update_product_price_and_catalog_and_basket_list_modified() + decimal priceModification = 0.15M; + string userId = "JohnId"; + + using var catalogServer = new CatalogScenariosBase().CreateServer(); + using var basketServer = new BasketScenariosBase().CreateServer(); + var catalogClient = catalogServer.CreateClient(); + var basketClient = basketServer.CreateClient(); + + // GIVEN a product catalog list + var originalCatalogProducts = await GetCatalogAsync(catalogClient); + + // AND a user basket filled with products + var basket = ComposeBasket(userId, originalCatalogProducts.Data.Take(3)); + var res = await basketClient.PostAsync( + BasketScenariosBase.Post.CreateBasket, + new StringContent(JsonSerializer.Serialize(basket), UTF8Encoding.UTF8, "application/json") + ); + + // WHEN the price of one product is modified in the catalog + var itemToModify = basket.Items[2]; + var oldPrice = itemToModify.UnitPrice; + var newPrice = oldPrice + priceModification; + var pRes = await catalogClient.PutAsync(CatalogScenariosBase.Put.UpdateCatalogProduct, new StringContent(ChangePrice(itemToModify, newPrice, originalCatalogProducts), UTF8Encoding.UTF8, "application/json")); + + var modifiedCatalogProducts = await GetCatalogAsync(catalogClient); + + var itemUpdated = await GetUpdatedBasketItem(newPrice, itemToModify.ProductId, userId, basketClient); + + if (itemUpdated == null) { - decimal priceModification = 0.15M; - string userId = "JohnId"; + Assert.False(true, $"The basket service has not been updated."); + } + else + { + //THEN the product price changes in the catalog + Assert.Equal(newPrice, modifiedCatalogProducts.Data.Single(it => it.Id == itemToModify.ProductId).Price); - using (var catalogServer = new CatalogScenariosBase().CreateServer()) - using (var basketServer = new BasketScenariosBase().CreateServer()) - { - var catalogClient = catalogServer.CreateClient(); - var basketClient = basketServer.CreateClient(); - - // GIVEN a product catalog list - var originalCatalogProducts = await GetCatalogAsync(catalogClient); - - // AND a user basket filled with products - var basket = ComposeBasket(userId, originalCatalogProducts.Data.Take(3)); - var res = await basketClient.PostAsync( - BasketScenariosBase.Post.CreateBasket, - new StringContent(JsonConvert.SerializeObject(basket), UTF8Encoding.UTF8, "application/json") - ); - - // WHEN the price of one product is modified in the catalog - var itemToModify = basket.Items[2]; - var oldPrice = itemToModify.UnitPrice; - var newPrice = oldPrice + priceModification; - var pRes = await catalogClient.PutAsync(CatalogScenariosBase.Put.UpdateCatalogProduct, new StringContent(ChangePrice(itemToModify, newPrice, originalCatalogProducts), UTF8Encoding.UTF8, "application/json")); - - var modifiedCatalogProducts = await GetCatalogAsync(catalogClient); - - var itemUpdated = await GetUpdatedBasketItem(newPrice, itemToModify.ProductId, userId, basketClient); - - if (itemUpdated == null) - { - Assert.False(true, $"The basket service has not been updated."); - } - else - { - //THEN the product price changes in the catalog - Assert.Equal(newPrice, modifiedCatalogProducts.Data.Single(it => it.Id == itemToModify.ProductId).Price); - - // AND the products in the basket reflects the changed priced and the original price - Assert.Equal(newPrice, itemUpdated.UnitPrice); - Assert.Equal(oldPrice, itemUpdated.OldUnitPrice); - } - } + // AND the products in the basket reflects the changed priced and the original price + Assert.Equal(newPrice, itemUpdated.UnitPrice); + Assert.Equal(oldPrice, itemUpdated.OldUnitPrice); } + } + + private async Task GetUpdatedBasketItem(decimal newPrice, int productId, string userId, HttpClient basketClient) + { + bool continueLoop = true; + var counter = 0; + BasketItem itemUpdated = null; - private async Task GetUpdatedBasketItem(decimal newPrice, int productId, string userId, HttpClient basketClient) + while (continueLoop && counter < 20) { - bool continueLoop = true; - var counter = 0; - BasketItem itemUpdated = null; + //get the basket and verify that the price of the modified product is updated + var basketGetResponse = await basketClient.GetAsync(BasketScenariosBase.Get.GetBasketByCustomer(userId)); + var basketUpdated = JsonSerializer.Deserialize(await basketGetResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); - while (continueLoop && counter < 20) + itemUpdated = basketUpdated.Items.Single(pr => pr.ProductId == productId); + + if (itemUpdated.UnitPrice == newPrice) { - //get the basket and verify that the price of the modified product is updated - var basketGetResponse = await basketClient.GetAsync(BasketScenariosBase.Get.GetBasketByCustomer(userId)); - var basketUpdated = JsonConvert.DeserializeObject(await basketGetResponse.Content.ReadAsStringAsync()); - - itemUpdated = basketUpdated.Items.Single(pr => pr.ProductId == productId); - - if (itemUpdated.UnitPrice == newPrice) - { - continueLoop = false; - } - else - { - counter++; - await Task.Delay(100); - } + continueLoop = false; + } + else + { + counter++; + await Task.Delay(100); } - - return itemUpdated; } - private async Task> GetCatalogAsync(HttpClient catalogClient) - { - var response = await catalogClient.GetAsync(CatalogScenariosBase.Get.Items); - var items = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject>(items); - } + return itemUpdated; + } - private string ChangePrice(BasketItem itemToModify, decimal newPrice, PaginatedItemsViewModel catalogProducts) + private async Task> GetCatalogAsync(HttpClient catalogClient) + { + var response = await catalogClient.GetAsync(CatalogScenariosBase.Get.Items); + var items = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize>(items, new JsonSerializerOptions { - var catalogProduct = catalogProducts.Data.Single(pr => pr.Id == itemToModify.ProductId); - catalogProduct.Price = newPrice; - return JsonConvert.SerializeObject(catalogProduct); - } + PropertyNameCaseInsensitive = true + }); + } - private CustomerBasket ComposeBasket(string customerId, IEnumerable items) + private string ChangePrice(BasketItem itemToModify, decimal newPrice, PaginatedItemsViewModel catalogProducts) + { + var catalogProduct = catalogProducts.Data.Single(pr => pr.Id == itemToModify.ProductId); + catalogProduct.Price = newPrice; + return JsonSerializer.Serialize(catalogProduct); + } + + private CustomerBasket ComposeBasket(string customerId, IEnumerable items) + { + var basket = new CustomerBasket(customerId); + foreach (var item in items) { - var basket = new CustomerBasket(customerId); - foreach (var item in items) + basket.Items.Add(new BasketItem() { - basket.Items.Add(new BasketItem() - { - Id = Guid.NewGuid().ToString(), - UnitPrice = item.Price, - PictureUrl = item.PictureUri, - ProductId = item.Id, - OldUnitPrice = 0, - ProductName = item.Name, - Quantity = 1 - }); - } - return basket; + Id = Guid.NewGuid().ToString(), + UnitPrice = item.Price, + PictureUrl = item.PictureUri, + ProductId = item.Id, + OldUnitPrice = 0, + ProductName = item.Name, + Quantity = 1 + }); } + return basket; } -} \ No newline at end of file +} diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs index 3a6e1c04b..e97a95e9d 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenarios.cs @@ -1,146 +1,139 @@ -using FunctionalTests.Extensions; -using FunctionalTests.Services.Basket; -using Microsoft.eShopOnContainers.Services.Basket.API.Model; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using WebMVC.Services.ModelDTOs; -using Xunit; - -namespace FunctionalTests.Services.Ordering +namespace FunctionalTests.Services.Ordering; + +public class OrderingScenarios : OrderingScenariosBase { - public class OrderingScenarios : OrderingScenariosBase + [Fact] + public async Task Cancel_basket_and_check_order_status_cancelled() { - [Fact] - public async Task Cancel_basket_and_check_order_status_cancelled() - { - using (var orderServer = new OrderingScenariosBase().CreateServer()) - using (var basketServer = new BasketScenariosBase().CreateServer()) - { - // Expected data - var cityExpected = $"city-{Guid.NewGuid()}"; - var orderStatusExpected = "cancelled"; + using var orderServer = new OrderingScenariosBase().CreateServer(); + using var basketServer = new BasketScenariosBase().CreateServer(); + // Expected data + var cityExpected = $"city-{Guid.NewGuid()}"; + var orderStatusExpected = "cancelled"; - var basketClient = basketServer.CreateIdempotentClient(); - var orderClient = orderServer.CreateIdempotentClient(); + var basketClient = basketServer.CreateIdempotentClient(); + var orderClient = orderServer.CreateIdempotentClient(); - // GIVEN a basket is created - var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); - await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket); + // GIVEN a basket is created + var contentBasket = new StringContent(BuildBasket(), UTF8Encoding.UTF8, "application/json"); + await basketClient.PostAsync(BasketScenariosBase.Post.CreateBasket, contentBasket); - // AND basket checkout is sent - await basketClient.PostAsync(BasketScenariosBase.Post.CheckoutOrder, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json")); + // AND basket checkout is sent + await basketClient.PostAsync(BasketScenariosBase.Post.CheckoutOrder, new StringContent(BuildCheckout(cityExpected), UTF8Encoding.UTF8, "application/json")); - // WHEN Order is created in Ordering.api - var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient); + // WHEN Order is created in Ordering.api + var newOrder = await TryGetNewOrderCreated(cityExpected, orderClient); - // AND Order is cancelled in Ordering.api - await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json")); + // AND Order is cancelled in Ordering.api + await orderClient.PutAsync(OrderingScenariosBase.Put.CancelOrder, new StringContent(BuildCancelOrder(newOrder.OrderNumber), UTF8Encoding.UTF8, "application/json")); - // AND the requested order is retrieved - var order = await TryGetOrder(newOrder.OrderNumber, orderClient); + // AND the requested order is retrieved + var order = await TryGetOrder(newOrder.OrderNumber, orderClient); - // THEN check status - Assert.Equal(orderStatusExpected, order.Status); - } - } + // THEN check status + Assert.Equal(orderStatusExpected, order.Status); + } - async Task TryGetOrder(string orderNumber, HttpClient orderClient) + async Task TryGetOrder(string orderNumber, HttpClient orderClient) + { + var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders); + var orders = JsonSerializer.Deserialize>(ordersGetResponse, new JsonSerializerOptions { - var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders); - var orders = JsonConvert.DeserializeObject>(ordersGetResponse); + PropertyNameCaseInsensitive = true + }); - return orders.Single(o => o.OrderNumber == orderNumber); - } + return orders.Single(o => o.OrderNumber == orderNumber); + } + + private async Task TryGetNewOrderCreated(string city, HttpClient orderClient) + { + var counter = 0; + Order order = null; - private async Task TryGetNewOrderCreated(string city, HttpClient orderClient) + while (counter < 20) { - var counter = 0; - Order order = null; + //get the orders and verify that the new order has been created + var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders); + var orders = JsonSerializer.Deserialize>(ordersGetResponse, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); - while (counter < 20) + if (orders == null || orders.Count == 0) { - //get the orders and verify that the new order has been created - var ordersGetResponse = await orderClient.GetStringAsync(OrderingScenariosBase.Get.Orders); - var orders = JsonConvert.DeserializeObject>(ordersGetResponse); - - if (orders == null || orders.Count == 0) - { - counter++; - await Task.Delay(100); - continue; - } - - var lastOrder = orders.OrderByDescending(o => o.Date).First(); - int.TryParse(lastOrder.OrderNumber, out int id); - var orderDetails = await orderClient.GetStringAsync(OrderingScenariosBase.Get.OrderBy(id)); - order = JsonConvert.DeserializeObject(orderDetails); - order.City = city; - - if (IsOrderCreated(order, city)) - { - break; - } + counter++; + await Task.Delay(100); + continue; } - return order; - } + var lastOrder = orders.OrderByDescending(o => o.Date).First(); + int.TryParse(lastOrder.OrderNumber, out int id); + var orderDetails = await orderClient.GetStringAsync(OrderingScenariosBase.Get.OrderBy(id)); + order = JsonSerializer.Deserialize(orderDetails, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + + order.City = city; - private bool IsOrderCreated(Order order, string city) - { - return order.City == city; + if (IsOrderCreated(order, city)) + { + break; + } } - string BuildBasket() + return order; + } + + private bool IsOrderCreated(Order order, string city) + { + return order.City == city; + } + + string BuildBasket() + { + var order = new CustomerBasket("9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"); + order.Items = new List() { - var order = new CustomerBasket("9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"); - order.Items = new List() + new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem() { - new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem() - { - Id = "1", - ProductName = "ProductName", - ProductId = 1, - UnitPrice = 10, - Quantity = 1 - } - }; - return JsonConvert.SerializeObject(order); - } + Id = "1", + ProductName = "ProductName", + ProductId = 1, + UnitPrice = 10, + Quantity = 1 + } + }; + return JsonSerializer.Serialize(order); + } - string BuildCancelOrder(string orderId) + string BuildCancelOrder(string orderId) + { + var order = new OrderDTO() { - var order = new OrderDTO() - { - OrderNumber = orderId - }; - return JsonConvert.SerializeObject(order); - } + OrderNumber = orderId + }; + return JsonSerializer.Serialize(order); + } - string BuildCheckout(string cityExpected) + string BuildCheckout(string cityExpected) + { + var checkoutBasket = new BasketDTO() { - var checkoutBasket = new BasketDTO() - { - City = cityExpected, - Street = "street", - State = "state", - Country = "coutry", - ZipCode = "zipcode", - CardNumber = "1111111111111", - CardHolderName = "CardHolderName", - CardExpiration = DateTime.Now.AddYears(1), - CardSecurityNumber = "123", - CardTypeId = 1, - Buyer = "Buyer", - RequestId = Guid.NewGuid() - }; - - return JsonConvert.SerializeObject(checkoutBasket); - } + City = cityExpected, + Street = "street", + State = "state", + Country = "coutry", + ZipCode = "zipcode", + CardNumber = "1111111111111", + CardHolderName = "CardHolderName", + CardExpiration = DateTime.Now.AddYears(1), + CardSecurityNumber = "123", + CardTypeId = 1, + Buyer = "Buyer", + RequestId = Guid.NewGuid() + }; + + return JsonSerializer.Serialize(checkoutBasket); } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenariosBase.cs b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenariosBase.cs index 487e435d2..fce6bca18 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenariosBase.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingScenariosBase.cs @@ -1,77 +1,63 @@ -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.TestHost; -using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; -using Microsoft.eShopOnContainers.Services.Ordering.API; -using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; -using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using System.IO; -using System.Reflection; +namespace FunctionalTests.Services.Ordering; -namespace FunctionalTests.Services.Ordering +public class OrderingScenariosBase { - public class OrderingScenariosBase + public TestServer CreateServer() { - public TestServer CreateServer() - { - var path = Assembly.GetAssembly(typeof(OrderingScenariosBase)) - .Location; - - var hostBuilder = new WebHostBuilder() - .UseContentRoot(Path.GetDirectoryName(path)) - .ConfigureAppConfiguration(cb => - { - cb.AddJsonFile("Services/Ordering/appsettings.json", optional: false) - .AddEnvironmentVariables(); - }).UseStartup(); + var path = Assembly.GetAssembly(typeof(OrderingScenariosBase)) + .Location; - var testServer = new TestServer(hostBuilder); + var hostBuilder = new WebHostBuilder() + .UseContentRoot(Path.GetDirectoryName(path)) + .ConfigureAppConfiguration(cb => + { + cb.AddJsonFile("Services/Ordering/appsettings.json", optional: false) + .AddEnvironmentVariables(); + }).UseStartup(); - testServer.Host - .MigrateDbContext((context, services) => - { - var env = services.GetService(); - var settings = services.GetService>(); - var logger = services.GetService>(); + var testServer = new TestServer(hostBuilder); - new OrderingContextSeed() - .SeedAsync(context, env, settings, logger) - .Wait(); - }) - .MigrateDbContext((_, __) => { }); + testServer.Host + .MigrateDbContext((context, services) => + { + var env = services.GetService(); + var settings = services.GetService>(); + var logger = services.GetService>(); - return testServer; - } + new OrderingContextSeed() + .SeedAsync(context, env, settings, logger) + .Wait(); + }) + .MigrateDbContext((_, __) => { }); - public static class Get - { - public static string Orders = "api/v1/orders"; + return testServer; + } - public static string OrderBy(int id) - { - return $"api/v1/orders/{id}"; - } - } + public static class Get + { + public static string Orders = "api/v1/orders"; - public static class Post + public static string OrderBy(int id) { - public static string AddNewOrder = "api/v1/orders/new"; + return $"api/v1/orders/{id}"; } + } - public static class Put - { - public static string CancelOrder = "api/v1/orders/cancel"; - } + public static class Post + { + public static string AddNewOrder = "api/v1/orders/new"; + } - public static class Delete + public static class Put + { + public static string CancelOrder = "api/v1/orders/cancel"; + } + + public static class Delete + { + public static string OrderBy(int id) { - public static string OrderBy(int id) - { - return $"api/v1/orders/{id}"; - } + return $"api/v1/orders/{id}"; } } } diff --git a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingTestsStartup.cs b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingTestsStartup.cs index 74708dec0..f6f3d8e51 100644 --- a/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingTestsStartup.cs +++ b/src/Tests/Services/Application.FunctionalTests/Services/Ordering/OrderingTestsStartup.cs @@ -1,27 +1,22 @@ -using FunctionalTests.Middleware; -using Microsoft.AspNetCore.Builder; +namespace FunctionalTests.Services.Ordering; using Microsoft.eShopOnContainers.Services.Ordering.API; -using Microsoft.Extensions.Configuration; -namespace FunctionalTests.Services.Ordering +public class OrderingTestsStartup : Startup { - public class OrderingTestsStartup : Startup + public OrderingTestsStartup(IConfiguration env) : base(env) { - public OrderingTestsStartup(IConfiguration env) : base(env) + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) { + app.UseMiddleware(); + app.UseAuthorization(); } - - protected override void ConfigureAuth(IApplicationBuilder app) + else { - if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) - { - app.UseMiddleware(); - app.UseAuthorization(); - } - else - { - base.ConfigureAuth(app); - } + base.ConfigureAuth(app); } } } diff --git a/src/Web/WebMVC/AppSettings.cs b/src/Web/WebMVC/AppSettings.cs index 17a37b1fc..ae0a02650 100644 --- a/src/Web/WebMVC/AppSettings.cs +++ b/src/Web/WebMVC/AppSettings.cs @@ -1,30 +1,29 @@ -namespace Microsoft.eShopOnContainers.WebMVC +namespace Microsoft.eShopOnContainers.WebMVC; + +public class AppSettings { - public class AppSettings - { - //public Connectionstrings ConnectionStrings { get; set; } - public string PurchaseUrl { get; set; } - public string SignalrHubUrl { get; set; } - public bool ActivateCampaignDetailFunction { get; set; } - public Logging Logging { get; set; } - public bool UseCustomizationData { get; set; } - } + //public Connectionstrings ConnectionStrings { get; set; } + public string PurchaseUrl { get; set; } + public string SignalrHubUrl { get; set; } + public bool ActivateCampaignDetailFunction { get; set; } + public Logging Logging { get; set; } + public bool UseCustomizationData { get; set; } +} - public class Connectionstrings - { - public string DefaultConnection { get; set; } - } +public class Connectionstrings +{ + public string DefaultConnection { get; set; } +} - public class Logging - { - public bool IncludeScopes { get; set; } - public Loglevel LogLevel { get; set; } - } +public class Logging +{ + public bool IncludeScopes { get; set; } + public Loglevel LogLevel { get; set; } +} - public class Loglevel - { - public string Default { get; set; } - public string System { get; set; } - public string Microsoft { get; set; } - } +public class Loglevel +{ + public string Default { get; set; } + public string System { get; set; } + public string Microsoft { get; set; } } diff --git a/src/Web/WebMVC/Controllers/AccountController.cs b/src/Web/WebMVC/Controllers/AccountController.cs index fba04f26d..e2a191bd2 100644 --- a/src/Web/WebMVC/Controllers/AccountController.cs +++ b/src/Web/WebMVC/Controllers/AccountController.cs @@ -1,53 +1,42 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using System; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Microsoft.eShopOnContainers.WebMVC.Controllers +namespace Microsoft.eShopOnContainers.WebMVC.Controllers; + +[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] +public class AccountController : Controller { + private readonly ILogger _logger; + + public AccountController(ILogger logger) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] - public class AccountController : Controller + public async Task SignIn(string returnUrl) { - private readonly ILogger _logger; + var user = User as ClaimsPrincipal; + var token = await HttpContext.GetTokenAsync("access_token"); - public AccountController(ILogger logger) - { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + _logger.LogInformation("----- User {@User} authenticated into {AppName}", user, Program.AppName); - [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] - public async Task SignIn(string returnUrl) + if (token != null) { - var user = User as ClaimsPrincipal; - var token = await HttpContext.GetTokenAsync("access_token"); - - _logger.LogInformation("----- User {@User} authenticated into {AppName}", user, Program.AppName); - - if (token != null) - { - ViewData["access_token"] = token; - } - - // "Catalog" because UrlHelper doesn't support nameof() for controllers - // https://github.com/aspnet/Mvc/issues/5853 - return RedirectToAction(nameof(CatalogController.Index), "Catalog"); + ViewData["access_token"] = token; } - public async Task Signout() - { - await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); - await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); - - // "Catalog" because UrlHelper doesn't support nameof() for controllers - // https://github.com/aspnet/Mvc/issues/5853 - var homeUrl = Url.Action(nameof(CatalogController.Index), "Catalog"); - return new SignOutResult(OpenIdConnectDefaults.AuthenticationScheme, - new AspNetCore.Authentication.AuthenticationProperties { RedirectUri = homeUrl }); - } + // "Catalog" because UrlHelper doesn't support nameof() for controllers + // https://github.com/aspnet/Mvc/issues/5853 + return RedirectToAction(nameof(CatalogController.Index), "Catalog"); + } + + public async Task Signout() + { + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); + await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); + + // "Catalog" because UrlHelper doesn't support nameof() for controllers + // https://github.com/aspnet/Mvc/issues/5853 + var homeUrl = Url.Action(nameof(CatalogController.Index), "Catalog"); + return new SignOutResult(OpenIdConnectDefaults.AuthenticationScheme, + new AspNetCore.Authentication.AuthenticationProperties { RedirectUri = homeUrl }); } } diff --git a/src/Web/WebMVC/Controllers/CartController.cs b/src/Web/WebMVC/Controllers/CartController.cs index d7e577c25..fc506ec43 100644 --- a/src/Web/WebMVC/Controllers/CartController.cs +++ b/src/Web/WebMVC/Controllers/CartController.cs @@ -1,89 +1,79 @@ -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.WebMVC.Controllers; -namespace Microsoft.eShopOnContainers.WebMVC.Controllers +[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] +public class CartController : Controller { - [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] - public class CartController : Controller + private readonly IBasketService _basketSvc; + private readonly ICatalogService _catalogSvc; + private readonly IIdentityParser _appUserParser; + + public CartController(IBasketService basketSvc, ICatalogService catalogSvc, IIdentityParser appUserParser) { - private readonly IBasketService _basketSvc; - private readonly ICatalogService _catalogSvc; - private readonly IIdentityParser _appUserParser; + _basketSvc = basketSvc; + _catalogSvc = catalogSvc; + _appUserParser = appUserParser; + } - public CartController(IBasketService basketSvc, ICatalogService catalogSvc, IIdentityParser appUserParser) + public async Task Index() + { + try { - _basketSvc = basketSvc; - _catalogSvc = catalogSvc; - _appUserParser = appUserParser; - } + var user = _appUserParser.Parse(HttpContext.User); + var vm = await _basketSvc.GetBasket(user); - public async Task Index() + return View(vm); + } + catch (Exception ex) { - try - { - var user = _appUserParser.Parse(HttpContext.User); - var vm = await _basketSvc.GetBasket(user); - - return View(vm); - } - catch (Exception ex) - { - HandleException(ex); - } - - return View(); + HandleException(ex); } + return View(); + } + - [HttpPost] - public async Task Index(Dictionary quantities, string action) + [HttpPost] + public async Task Index(Dictionary quantities, string action) + { + try { - try + var user = _appUserParser.Parse(HttpContext.User); + var basket = await _basketSvc.SetQuantities(user, quantities); + if (action == "[ Checkout ]") { - var user = _appUserParser.Parse(HttpContext.User); - var basket = await _basketSvc.SetQuantities(user, quantities); - if (action == "[ Checkout ]") - { - return RedirectToAction("Create", "Order"); - } + return RedirectToAction("Create", "Order"); } - catch (Exception ex) - { - HandleException(ex); - } - - return View(); + } + catch (Exception ex) + { + HandleException(ex); } - public async Task AddToCart(CatalogItem productDetails) + return View(); + } + + public async Task AddToCart(CatalogItem productDetails) + { + try { - try - { - if (productDetails?.Id != null) - { - var user = _appUserParser.Parse(HttpContext.User); - await _basketSvc.AddItemToBasket(user, productDetails.Id); - } - return RedirectToAction("Index", "Catalog"); - } - catch (Exception ex) + if (productDetails?.Id != null) { - // Catch error when Basket.api is in circuit-opened mode - HandleException(ex); + var user = _appUserParser.Parse(HttpContext.User); + await _basketSvc.AddItemToBasket(user, productDetails.Id); } - - return RedirectToAction("Index", "Catalog", new { errorMsg = ViewBag.BasketInoperativeMsg }); + return RedirectToAction("Index", "Catalog"); } - - private void HandleException(Exception ex) + catch (Exception ex) { - ViewBag.BasketInoperativeMsg = $"Basket Service is inoperative {ex.GetType().Name} - {ex.Message}"; + // Catch error when Basket.api is in circuit-opened mode + HandleException(ex); } + + return RedirectToAction("Index", "Catalog", new { errorMsg = ViewBag.BasketInoperativeMsg }); + } + + private void HandleException(Exception ex) + { + ViewBag.BasketInoperativeMsg = $"Basket Service is inoperative {ex.GetType().Name} - {ex.Message}"; } } diff --git a/src/Web/WebMVC/Controllers/CatalogController.cs b/src/Web/WebMVC/Controllers/CatalogController.cs index 0ac5ecacc..319d88219 100644 --- a/src/Web/WebMVC/Controllers/CatalogController.cs +++ b/src/Web/WebMVC/Controllers/CatalogController.cs @@ -1,45 +1,37 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels; -using Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.WebMVC.Controllers; -namespace Microsoft.eShopOnContainers.WebMVC.Controllers +public class CatalogController : Controller { - public class CatalogController : Controller - { - private ICatalogService _catalogSvc; + private ICatalogService _catalogSvc; - public CatalogController(ICatalogService catalogSvc) => - _catalogSvc = catalogSvc; + public CatalogController(ICatalogService catalogSvc) => + _catalogSvc = catalogSvc; - public async Task Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page, [FromQuery] string errorMsg) + public async Task Index(int? BrandFilterApplied, int? TypesFilterApplied, int? page, [FromQuery] string errorMsg) + { + var itemsPage = 9; + var catalog = await _catalogSvc.GetCatalogItems(page ?? 0, itemsPage, BrandFilterApplied, TypesFilterApplied); + var vm = new IndexViewModel() { - var itemsPage = 10; - var catalog = await _catalogSvc.GetCatalogItems(page ?? 0, itemsPage, BrandFilterApplied, TypesFilterApplied); - var vm = new IndexViewModel() + CatalogItems = catalog.Data, + Brands = await _catalogSvc.GetBrands(), + Types = await _catalogSvc.GetTypes(), + BrandFilterApplied = BrandFilterApplied ?? 0, + TypesFilterApplied = TypesFilterApplied ?? 0, + PaginationInfo = new PaginationInfo() { - CatalogItems = catalog.Data, - Brands = await _catalogSvc.GetBrands(), - Types = await _catalogSvc.GetTypes(), - BrandFilterApplied = BrandFilterApplied ?? 0, - TypesFilterApplied = TypesFilterApplied ?? 0, - PaginationInfo = new PaginationInfo() - { - ActualPage = page ?? 0, - ItemsPerPage = catalog.Data.Count, - TotalItems = catalog.Count, - TotalPages = (int)Math.Ceiling(((decimal)catalog.Count / itemsPage)) - } - }; + ActualPage = page ?? 0, + ItemsPerPage = catalog.Data.Count, + TotalItems = catalog.Count, + TotalPages = (int)Math.Ceiling(((decimal)catalog.Count / itemsPage)) + } + }; - vm.PaginationInfo.Next = (vm.PaginationInfo.ActualPage == vm.PaginationInfo.TotalPages - 1) ? "is-disabled" : ""; - vm.PaginationInfo.Previous = (vm.PaginationInfo.ActualPage == 0) ? "is-disabled" : ""; + vm.PaginationInfo.Next = (vm.PaginationInfo.ActualPage == vm.PaginationInfo.TotalPages - 1) ? "is-disabled" : ""; + vm.PaginationInfo.Previous = (vm.PaginationInfo.ActualPage == 0) ? "is-disabled" : ""; - ViewBag.BasketInoperativeMsg = errorMsg; + ViewBag.BasketInoperativeMsg = errorMsg; - return View(vm); - } + return View(vm); } } \ No newline at end of file diff --git a/src/Web/WebMVC/Controllers/ErrorController.cs b/src/Web/WebMVC/Controllers/ErrorController.cs index 222c7be51..0ce36eb6f 100644 --- a/src/Web/WebMVC/Controllers/ErrorController.cs +++ b/src/Web/WebMVC/Controllers/ErrorController.cs @@ -1,9 +1,6 @@ -using Microsoft.AspNetCore.Mvc; +namespace WebMVC.Controllers; -namespace WebMVC.Controllers +public class ErrorController : Controller { - public class ErrorController : Controller - { - public IActionResult Error() => View(); - } + public IActionResult Error() => View(); } diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs index d5e98552a..a80d54072 100644 --- a/src/Web/WebMVC/Controllers/OrderController.cs +++ b/src/Web/WebMVC/Controllers/OrderController.cs @@ -1,82 +1,75 @@ -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; +namespace Microsoft.eShopOnContainers.WebMVC.Controllers; + using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System; -using System.Threading.Tasks; -namespace Microsoft.eShopOnContainers.WebMVC.Controllers +[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] +public class OrderController : Controller { - [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] - public class OrderController : Controller + private IOrderingService _orderSvc; + private IBasketService _basketSvc; + private readonly IIdentityParser _appUserParser; + public OrderController(IOrderingService orderSvc, IBasketService basketSvc, IIdentityParser appUserParser) { - private IOrderingService _orderSvc; - private IBasketService _basketSvc; - private readonly IIdentityParser _appUserParser; - public OrderController(IOrderingService orderSvc, IBasketService basketSvc, IIdentityParser appUserParser) - { - _appUserParser = appUserParser; - _orderSvc = orderSvc; - _basketSvc = basketSvc; - } + _appUserParser = appUserParser; + _orderSvc = orderSvc; + _basketSvc = basketSvc; + } - public async Task Create() - { + public async Task Create() + { - var user = _appUserParser.Parse(HttpContext.User); - var order = await _basketSvc.GetOrderDraft(user.Id); - var vm = _orderSvc.MapUserInfoIntoOrder(user, order); - vm.CardExpirationShortFormat(); + var user = _appUserParser.Parse(HttpContext.User); + var order = await _basketSvc.GetOrderDraft(user.Id); + var vm = _orderSvc.MapUserInfoIntoOrder(user, order); + vm.CardExpirationShortFormat(); - return View(vm); - } + return View(vm); + } - [HttpPost] - public async Task Checkout(Order model) + [HttpPost] + public async Task Checkout(Order model) + { + try { - try + if (ModelState.IsValid) { - if (ModelState.IsValid) - { - var user = _appUserParser.Parse(HttpContext.User); - var basket = _orderSvc.MapOrderToBasket(model); + var user = _appUserParser.Parse(HttpContext.User); + var basket = _orderSvc.MapOrderToBasket(model); - await _basketSvc.Checkout(basket); + await _basketSvc.Checkout(basket); - //Redirect to historic list. - return RedirectToAction("Index"); - } - } - catch (Exception ex) - { - ModelState.AddModelError("Error", $"It was not possible to create a new order, please try later on ({ex.GetType().Name} - {ex.Message})"); + //Redirect to historic list. + return RedirectToAction("Index"); } - - return View("Create", model); } - - public async Task Cancel(string orderId) + catch (Exception ex) { - await _orderSvc.CancelOrder(orderId); - - //Redirect to historic list. - return RedirectToAction("Index"); + ModelState.AddModelError("Error", $"It was not possible to create a new order, please try later on ({ex.GetType().Name} - {ex.Message})"); } - public async Task Detail(string orderId) - { - var user = _appUserParser.Parse(HttpContext.User); + return View("Create", model); + } - var order = await _orderSvc.GetOrder(user, orderId); - return View(order); - } + public async Task Cancel(string orderId) + { + await _orderSvc.CancelOrder(orderId); - public async Task Index(Order item) - { - var user = _appUserParser.Parse(HttpContext.User); - var vm = await _orderSvc.GetMyOrders(user); - return View(vm); - } + //Redirect to historic list. + return RedirectToAction("Index"); + } + + public async Task Detail(string orderId) + { + var user = _appUserParser.Parse(HttpContext.User); + + var order = await _orderSvc.GetOrder(user, orderId); + return View(order); + } + + public async Task Index(Order item) + { + var user = _appUserParser.Parse(HttpContext.User); + var vm = await _orderSvc.GetMyOrders(user); + return View(vm); } -} \ No newline at end of file +} diff --git a/src/Web/WebMVC/Controllers/OrderManagementController.cs b/src/Web/WebMVC/Controllers/OrderManagementController.cs index 27ad642ba..ac699bade 100644 --- a/src/Web/WebMVC/Controllers/OrderManagementController.cs +++ b/src/Web/WebMVC/Controllers/OrderManagementController.cs @@ -1,41 +1,32 @@ -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System.Threading.Tasks; -using WebMVC.Services.ModelDTOs; +namespace WebMVC.Controllers; -namespace WebMVC.Controllers +[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] +public class OrderManagementController : Controller { - [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)] - public class OrderManagementController : Controller + private IOrderingService _orderSvc; + private readonly IIdentityParser _appUserParser; + public OrderManagementController(IOrderingService orderSvc, IIdentityParser appUserParser) { - private IOrderingService _orderSvc; - private readonly IIdentityParser _appUserParser; - public OrderManagementController(IOrderingService orderSvc, IIdentityParser appUserParser) - { - _appUserParser = appUserParser; - _orderSvc = orderSvc; - } + _appUserParser = appUserParser; + _orderSvc = orderSvc; + } - public async Task Index() - { - var user = _appUserParser.Parse(HttpContext.User); - var vm = await _orderSvc.GetMyOrders(user); + public async Task Index() + { + var user = _appUserParser.Parse(HttpContext.User); + var vm = await _orderSvc.GetMyOrders(user); - return View(vm); - } + return View(vm); + } - [HttpPost] - public async Task OrderProcess(string orderId, string actionCode) + [HttpPost] + public async Task OrderProcess(string orderId, string actionCode) + { + if (OrderProcessAction.Ship.Code == actionCode) { - if (OrderProcessAction.Ship.Code == actionCode) - { - await _orderSvc.ShipOrder(orderId); - } - - return RedirectToAction("Index"); + await _orderSvc.ShipOrder(orderId); } + + return RedirectToAction("Index"); } } diff --git a/src/Web/WebMVC/Controllers/TestController.cs b/src/Web/WebMVC/Controllers/TestController.cs index a80fe9ad8..3054038ee 100644 --- a/src/Web/WebMVC/Controllers/TestController.cs +++ b/src/Web/WebMVC/Controllers/TestController.cs @@ -1,61 +1,52 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Newtonsoft.Json; -using System.Net.Http; -using System.Threading.Tasks; - -namespace WebMVC.Controllers +namespace WebMVC.Controllers; + +class TestPayload { - class TestPayload - { - public int CatalogItemId { get; set; } + public int CatalogItemId { get; set; } - public string BasketId { get; set; } + public string BasketId { get; set; } - public int Quantity { get; set; } - } + public int Quantity { get; set; } +} - [Authorize] - public class TestController : Controller +[Authorize] +public class TestController : Controller +{ + private readonly IHttpClientFactory _client; + private readonly IIdentityParser _appUserParser; + + public TestController(IHttpClientFactory client, IIdentityParser identityParser) { - private readonly IHttpClientFactory _client; - private readonly IIdentityParser _appUserParser; + _client = client; + _appUserParser = identityParser; + } - public TestController(IHttpClientFactory client, IIdentityParser identityParser) - { - _client = client; - _appUserParser = identityParser; - } + public async Task Ocelot() + { + var url = "http://apigw/shopping/api/v1/basket/items"; - public async Task Ocelot() + var payload = new TestPayload() { - var url = "http://apigw/shopping/api/v1/basket/items"; - - var payload = new TestPayload() - { - CatalogItemId = 1, - Quantity = 1, - BasketId = _appUserParser.Parse(User).Id - }; + CatalogItemId = 1, + Quantity = 1, + BasketId = _appUserParser.Parse(User).Id + }; - var content = new StringContent(JsonConvert.SerializeObject(payload), System.Text.Encoding.UTF8, "application/json"); + var content = new StringContent(JsonSerializer.Serialize(payload), System.Text.Encoding.UTF8, "application/json"); - var response = await _client.CreateClient(nameof(IBasketService)) - .PostAsync(url, content); + var response = await _client.CreateClient(nameof(IBasketService)) + .PostAsync(url, content); - if (response.IsSuccessStatusCode) - { - var str = await response.Content.ReadAsStringAsync(); + if (response.IsSuccessStatusCode) + { + var str = await response.Content.ReadAsStringAsync(); - return Ok(str); - } - else - { - return Ok(new { response.StatusCode, response.ReasonPhrase }); - } + return Ok(str); + } + else + { + return Ok(new { response.StatusCode, response.ReasonPhrase }); } } } diff --git a/src/Web/WebMVC/Dockerfile b/src/Web/WebMVC/Dockerfile index bab4109b5..470de25d2 100644 --- a/src/Web/WebMVC/Dockerfile +++ b/src/Web/WebMVC/Dockerfile @@ -1,8 +1,8 @@ -FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src # It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles @@ -13,6 +13,7 @@ COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator. COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" diff --git a/src/Web/WebMVC/Dockerfile.develop b/src/Web/WebMVC/Dockerfile.develop index c22717a35..2a6115246 100644 --- a/src/Web/WebMVC/Dockerfile.develop +++ b/src/Web/WebMVC/Dockerfile.develop @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:5.0.102-ca-patch-buster-slim +FROM mcr.microsoft.com/dotnet/sdk:5.0 ARG BUILD_CONFIGURATION=Debug ENV ASPNETCORE_ENVIRONMENT=Development ENV DOTNET_USE_POLLING_FILE_WATCHER=true diff --git a/src/Web/WebMVC/Extensions/HttpClientExtensions.cs b/src/Web/WebMVC/Extensions/HttpClientExtensions.cs index 087c0dd8a..d1b11c9f7 100644 --- a/src/Web/WebMVC/Extensions/HttpClientExtensions.cs +++ b/src/Web/WebMVC/Extensions/HttpClientExtensions.cs @@ -1,35 +1,28 @@ -using System; -using System.IdentityModel.Tokens.Jwt; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; +namespace Microsoft.eShopOnContainers.WebMVC.Extensions; -namespace Microsoft.eShopOnContainers.WebMVC.Extensions +public static class HttpClientExtensions { - public static class HttpClientExtensions - { - public static void SetBasicAuthentication(this HttpClient client, string userName, string password) => - client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(userName, password); + public static void SetBasicAuthentication(this HttpClient client, string userName, string password) => + client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(userName, password); - public static void SetToken(this HttpClient client, string scheme, string token) => - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(scheme, token); + public static void SetToken(this HttpClient client, string scheme, string token) => + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(scheme, token); - public static void SetBearerToken(this HttpClient client, string token) => - client.SetToken(JwtConstants.TokenType, token); - } + public static void SetBearerToken(this HttpClient client, string token) => + client.SetToken(JwtConstants.TokenType, token); +} - public class BasicAuthenticationHeaderValue : AuthenticationHeaderValue - { - public BasicAuthenticationHeaderValue(string userName, string password) - : base("Basic", EncodeCredential(userName, password)) - { } +public class BasicAuthenticationHeaderValue : AuthenticationHeaderValue +{ + public BasicAuthenticationHeaderValue(string userName, string password) + : base("Basic", EncodeCredential(userName, password)) + { } - private static string EncodeCredential(string userName, string password) - { - Encoding encoding = Encoding.GetEncoding("iso-8859-1"); - string credential = String.Format("{0}:{1}", userName, password); + private static string EncodeCredential(string userName, string password) + { + Encoding encoding = Encoding.GetEncoding("iso-8859-1"); + string credential = String.Format("{0}:{1}", userName, password); - return Convert.ToBase64String(encoding.GetBytes(credential)); - } + return Convert.ToBase64String(encoding.GetBytes(credential)); } } diff --git a/src/Web/WebMVC/Extensions/SessionExtensions.cs b/src/Web/WebMVC/Extensions/SessionExtensions.cs index 47b079158..8175c26c4 100644 --- a/src/Web/WebMVC/Extensions/SessionExtensions.cs +++ b/src/Web/WebMVC/Extensions/SessionExtensions.cs @@ -1,17 +1,16 @@ -using Microsoft.AspNetCore.Http; -using Newtonsoft.Json; - - -public static class SessionExtensions +public static class SessionExtensions { public static void SetObject(this ISession session, string key, object value) => - session.SetString(key, JsonConvert.SerializeObject(value)); + session.SetString(key,JsonSerializer.Serialize(value)); public static T GetObject(this ISession session, string key) { var value = session.GetString(key); - return value == null ? default(T) : JsonConvert.DeserializeObject(value); + return value == null ? default(T) :JsonSerializer.Deserialize(value, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); } } diff --git a/src/Web/WebMVC/Infrastructure/API.cs b/src/Web/WebMVC/Infrastructure/API.cs index 0faeeb886..6e5ca68a2 100644 --- a/src/Web/WebMVC/Infrastructure/API.cs +++ b/src/Web/WebMVC/Infrastructure/API.cs @@ -1,86 +1,85 @@ -namespace WebMVC.Infrastructure +namespace WebMVC.Infrastructure; + +public static class API { - public static class API + + public static class Purchase + { + public static string AddItemToBasket(string baseUri) => $"{baseUri}/basket/items"; + public static string UpdateBasketItem(string baseUri) => $"{baseUri}/basket/items"; + + public static string GetOrderDraft(string baseUri, string basketId) => $"{baseUri}/order/draft/{basketId}"; + } + + public static class Basket { + public static string GetBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}"; + public static string UpdateBasket(string baseUri) => baseUri; + public static string CheckoutBasket(string baseUri) => $"{baseUri}/checkout"; + public static string CleanBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}"; + } - public static class Purchase + public static class Order + { + public static string GetOrder(string baseUri, string orderId) { - public static string AddItemToBasket(string baseUri) => $"{baseUri}/basket/items"; - public static string UpdateBasketItem(string baseUri) => $"{baseUri}/basket/items"; + return $"{baseUri}/{orderId}"; + } - public static string GetOrderDraft(string baseUri, string basketId) => $"{baseUri}/order/draft/{basketId}"; + public static string GetAllMyOrders(string baseUri) + { + return baseUri; } - public static class Basket + public static string AddNewOrder(string baseUri) { - public static string GetBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}"; - public static string UpdateBasket(string baseUri) => baseUri; - public static string CheckoutBasket(string baseUri) => $"{baseUri}/checkout"; - public static string CleanBasket(string baseUri, string basketId) => $"{baseUri}/{basketId}"; + return $"{baseUri}/new"; } - public static class Order + public static string CancelOrder(string baseUri) { - public static string GetOrder(string baseUri, string orderId) - { - return $"{baseUri}/{orderId}"; - } + return $"{baseUri}/cancel"; + } - public static string GetAllMyOrders(string baseUri) - { - return baseUri; - } + public static string ShipOrder(string baseUri) + { + return $"{baseUri}/ship"; + } + } - public static string AddNewOrder(string baseUri) + public static class Catalog + { + public static string GetAllCatalogItems(string baseUri, int page, int take, int? brand, int? type) + { + var filterQs = ""; + + if (type.HasValue) { - return $"{baseUri}/new"; - } + var brandQs = (brand.HasValue) ? brand.Value.ToString() : string.Empty; + filterQs = $"/type/{type.Value}/brand/{brandQs}"; - public static string CancelOrder(string baseUri) + } + else if (brand.HasValue) { - return $"{baseUri}/cancel"; + var brandQs = (brand.HasValue) ? brand.Value.ToString() : string.Empty; + filterQs = $"/type/all/brand/{brandQs}"; } - - public static string ShipOrder(string baseUri) + else { - return $"{baseUri}/ship"; + filterQs = string.Empty; } + + return $"{baseUri}items{filterQs}?pageIndex={page}&pageSize={take}"; } - public static class Catalog + public static string GetAllBrands(string baseUri) { - public static string GetAllCatalogItems(string baseUri, int page, int take, int? brand, int? type) - { - var filterQs = ""; - - if (type.HasValue) - { - var brandQs = (brand.HasValue) ? brand.Value.ToString() : string.Empty; - filterQs = $"/type/{type.Value}/brand/{brandQs}"; - - } - else if (brand.HasValue) - { - var brandQs = (brand.HasValue) ? brand.Value.ToString() : string.Empty; - filterQs = $"/type/all/brand/{brandQs}"; - } - else - { - filterQs = string.Empty; - } - - return $"{baseUri}items{filterQs}?pageIndex={page}&pageSize={take}"; - } - - public static string GetAllBrands(string baseUri) - { - return $"{baseUri}catalogBrands"; - } + return $"{baseUri}catalogBrands"; + } - public static string GetAllTypes(string baseUri) - { - return $"{baseUri}catalogTypes"; - } + public static string GetAllTypes(string baseUri) + { + return $"{baseUri}catalogTypes"; } } -} \ No newline at end of file +} diff --git a/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs index 255bd1649..e9f21a4f0 100644 --- a/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs +++ b/src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs @@ -1,49 +1,40 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Http; -using System.Collections.Generic; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; - -namespace WebMVC.Infrastructure +namespace WebMVC.Infrastructure; + +public class HttpClientAuthorizationDelegatingHandler + : DelegatingHandler { - public class HttpClientAuthorizationDelegatingHandler - : DelegatingHandler + private readonly IHttpContextAccessor _httpContextAccessor; + + public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor) { - private readonly IHttpContextAccessor _httpContextAccesor; + _httpContextAccessor = httpContextAccessor; + } - public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor) - { - _httpContextAccesor = httpContextAccesor; - } + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var authorizationHeader = _httpContextAccessor.HttpContext + .Request.Headers["Authorization"]; - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + if (!string.IsNullOrEmpty(authorizationHeader)) { - var authorizationHeader = _httpContextAccesor.HttpContext - .Request.Headers["Authorization"]; - - if (!string.IsNullOrEmpty(authorizationHeader)) - { - request.Headers.Add("Authorization", new List() { authorizationHeader }); - } - - var token = await GetToken(); + request.Headers.Add("Authorization", new List() { authorizationHeader }); + } - if (token != null) - { - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); - } + var token = await GetToken(); - return await base.SendAsync(request, cancellationToken); + if (token != null) + { + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } - async Task GetToken() - { - const string ACCESS_TOKEN = "access_token"; + return await base.SendAsync(request, cancellationToken); + } - return await _httpContextAccesor.HttpContext - .GetTokenAsync(ACCESS_TOKEN); - } + async Task GetToken() + { + const string ACCESS_TOKEN = "access_token"; + + return await _httpContextAccessor.HttpContext + .GetTokenAsync(ACCESS_TOKEN); } } diff --git a/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs b/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs index a59c757c0..798a9a034 100644 --- a/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs +++ b/src/Web/WebMVC/Infrastructure/HttpClientRequestIdDelegatingHandler.cs @@ -1,29 +1,23 @@ -using System; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; +namespace WebMVC.Infrastructure; -namespace WebMVC.Infrastructure +public class HttpClientRequestIdDelegatingHandler + : DelegatingHandler { - public class HttpClientRequestIdDelegatingHandler - : DelegatingHandler - { - public HttpClientRequestIdDelegatingHandler() - { - } + public HttpClientRequestIdDelegatingHandler() + { + } - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Put) { - if (request.Method == HttpMethod.Post || request.Method == HttpMethod.Put) + if (!request.Headers.Contains("x-requestid")) { - if (!request.Headers.Contains("x-requestid")) - { - request.Headers.Add("x-requestid", Guid.NewGuid().ToString()); - } + request.Headers.Add("x-requestid", Guid.NewGuid().ToString()); } - - return await base.SendAsync(request, cancellationToken); } + + return await base.SendAsync(request, cancellationToken); } -} +} \ No newline at end of file diff --git a/src/Web/WebMVC/Infrastructure/WebContextSeed.cs b/src/Web/WebMVC/Infrastructure/WebContextSeed.cs index 16696af9d..6ee7678e1 100644 --- a/src/Web/WebMVC/Infrastructure/WebContextSeed.cs +++ b/src/Web/WebMVC/Infrastructure/WebContextSeed.cs @@ -1,97 +1,83 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.eShopOnContainers.WebMVC; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; +namespace WebMVC.Infrastructure; using Serilog; -using System; -using System.IO; -using System.IO.Compression; -using System.Linq; -namespace WebMVC.Infrastructure +public class WebContextSeed { - public class WebContextSeed + public static void Seed(IApplicationBuilder applicationBuilder, IWebHostEnvironment env) { - public static void Seed(IApplicationBuilder applicationBuilder, IWebHostEnvironment env) - { - var log = Serilog.Log.Logger; + var log = Serilog.Log.Logger; - var settings = (AppSettings)applicationBuilder - .ApplicationServices.GetRequiredService>().Value; + var settings = (AppSettings)applicationBuilder + .ApplicationServices.GetRequiredService>().Value; - var useCustomizationData = settings.UseCustomizationData; - var contentRootPath = env.ContentRootPath; - var webroot = env.WebRootPath; + var useCustomizationData = settings.UseCustomizationData; + var contentRootPath = env.ContentRootPath; + var webroot = env.WebRootPath; - if (useCustomizationData) - { - GetPreconfiguredImages(contentRootPath, webroot, log); + if (useCustomizationData) + { + GetPreconfiguredImages(contentRootPath, webroot, log); - GetPreconfiguredCSS(contentRootPath, webroot, log); - } + GetPreconfiguredCSS(contentRootPath, webroot, log); } + } - static void GetPreconfiguredCSS(string contentRootPath, string webroot, ILogger log) + static void GetPreconfiguredCSS(string contentRootPath, string webroot, ILogger log) + { + try { - try - { - string overrideCssFile = Path.Combine(contentRootPath, "Setup", "override.css"); - if (!File.Exists(overrideCssFile)) - { - log.Error("Override css file '{FileName}' does not exists.", overrideCssFile); - return; - } - - string destinationFilename = Path.Combine(webroot, "css", "override.css"); - File.Copy(overrideCssFile, destinationFilename, true); - } - catch (Exception ex) + string overrideCssFile = Path.Combine(contentRootPath, "Setup", "override.css"); + if (!File.Exists(overrideCssFile)) { - log.Error(ex, "EXCEPTION ERROR: {Message}", ex.Message); + log.Error("Override css file '{FileName}' does not exists.", overrideCssFile); + return; } + + string destinationFilename = Path.Combine(webroot, "css", "override.css"); + File.Copy(overrideCssFile, destinationFilename, true); + } + catch (Exception ex) + { + log.Error(ex, "EXCEPTION ERROR: {Message}", ex.Message); } + } - static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger log) + static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger log) + { + try { - try + string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip"); + if (!File.Exists(imagesZipFile)) { - string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip"); - if (!File.Exists(imagesZipFile)) - { - log.Error("Zip file '{ZipFileName}' does not exists.", imagesZipFile); - return; - } + log.Error("Zip file '{ZipFileName}' does not exists.", imagesZipFile); + return; + } - string imagePath = Path.Combine(webroot, "images"); - string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); + string imagePath = Path.Combine(webroot, "images"); + string[] imageFiles = Directory.GetFiles(imagePath).Select(file => Path.GetFileName(file)).ToArray(); - using (ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read)) + using ZipArchive zip = ZipFile.Open(imagesZipFile, ZipArchiveMode.Read); + foreach (ZipArchiveEntry entry in zip.Entries) + { + if (imageFiles.Contains(entry.Name)) { - foreach (ZipArchiveEntry entry in zip.Entries) + string destinationFilename = Path.Combine(imagePath, entry.Name); + if (File.Exists(destinationFilename)) { - if (imageFiles.Contains(entry.Name)) - { - string destinationFilename = Path.Combine(imagePath, entry.Name); - if (File.Exists(destinationFilename)) - { - File.Delete(destinationFilename); - } - entry.ExtractToFile(destinationFilename); - } - else - { - log.Warning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); - } + File.Delete(destinationFilename); } + entry.ExtractToFile(destinationFilename); + } + else + { + log.Warning("Skipped file '{FileName}' in zipfile '{ZipFileName}'", entry.Name, imagesZipFile); } - } - catch (Exception ex) - { - log.Error(ex, "EXCEPTION ERROR: {Message}", ex.Message); } } - + catch (Exception ex) + { + log.Error(ex, "EXCEPTION ERROR: {Message}", ex.Message); + } } -} +} \ No newline at end of file diff --git a/src/Web/WebMVC/Program.cs b/src/Web/WebMVC/Program.cs index a95578718..b5aad7856 100644 --- a/src/Web/WebMVC/Program.cs +++ b/src/Web/WebMVC/Program.cs @@ -1,13 +1,4 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.eShopOnContainers.WebMVC; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using Serilog; -using System; -using System.IO; - -var configuration = GetConfiguration(); +var configuration = GetConfiguration(); Log.Logger = CreateSerilogLogger(configuration); @@ -70,7 +61,7 @@ IConfiguration GetConfiguration() } -public class Program +public partial class Program { private static readonly string _namespace = typeof(Startup).Namespace; public static readonly string AppName = _namespace.Substring(_namespace.LastIndexOf('.', _namespace.LastIndexOf('.') - 1) + 1); diff --git a/src/Web/WebMVC/Services/BasketService.cs b/src/Web/WebMVC/Services/BasketService.cs index 26985a671..eeadf37b7 100644 --- a/src/Web/WebMVC/Services/BasketService.cs +++ b/src/Web/WebMVC/Services/BasketService.cs @@ -1,121 +1,120 @@ -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using WebMVC.Infrastructure; -using WebMVC.Services.ModelDTOs; - -namespace Microsoft.eShopOnContainers.WebMVC.Services +namespace Microsoft.eShopOnContainers.WebMVC.Services; + +using Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public class BasketService : IBasketService { - public class BasketService : IBasketService + private readonly IOptions _settings; + private readonly HttpClient _apiClient; + private readonly ILogger _logger; + private readonly string _basketByPassUrl; + private readonly string _purchaseUrl; + + public BasketService(HttpClient httpClient, IOptions settings, ILogger logger) { - private readonly IOptions _settings; - private readonly HttpClient _apiClient; - private readonly ILogger _logger; - private readonly string _basketByPassUrl; - private readonly string _purchaseUrl; + _apiClient = httpClient; + _settings = settings; + _logger = logger; - public BasketService(HttpClient httpClient, IOptions settings, ILogger logger) - { - _apiClient = httpClient; - _settings = settings; - _logger = logger; + _basketByPassUrl = $"{_settings.Value.PurchaseUrl}/b/api/v1/basket"; + _purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1"; + } - _basketByPassUrl = $"{_settings.Value.PurchaseUrl}/b/api/v1/basket"; - _purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1"; - } + public async Task GetBasket(ApplicationUser user) + { + var uri = API.Basket.GetBasket(_basketByPassUrl, user.Id); + _logger.LogDebug("[GetBasket] -> Calling {Uri} to get the basket", uri); + var response = await _apiClient.GetAsync(uri); + _logger.LogDebug("[GetBasket] -> response code {StatusCode}", response.StatusCode); + var responseString = await response.Content.ReadAsStringAsync(); + return string.IsNullOrEmpty(responseString) ? + new Basket() { BuyerId = user.Id } : + JsonSerializer.Deserialize(responseString, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + } - public async Task GetBasket(ApplicationUser user) - { - var uri = API.Basket.GetBasket(_basketByPassUrl, user.Id); - _logger.LogDebug("[GetBasket] -> Calling {Uri} to get the basket", uri); - var response = await _apiClient.GetAsync(uri); - _logger.LogDebug("[GetBasket] -> response code {StatusCode}", response.StatusCode); - var responseString = await response.Content.ReadAsStringAsync(); - return string.IsNullOrEmpty(responseString) ? - new Basket() { BuyerId = user.Id } : - JsonConvert.DeserializeObject(responseString); - } - - public async Task UpdateBasket(Basket basket) - { - var uri = API.Basket.UpdateBasket(_basketByPassUrl); + public async Task UpdateBasket(Basket basket) + { + var uri = API.Basket.UpdateBasket(_basketByPassUrl); - var basketContent = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json"); + var basketContent = new StringContent(JsonSerializer.Serialize(basket), System.Text.Encoding.UTF8, "application/json"); - var response = await _apiClient.PostAsync(uri, basketContent); + var response = await _apiClient.PostAsync(uri, basketContent); - response.EnsureSuccessStatusCode(); + response.EnsureSuccessStatusCode(); - return basket; - } + return basket; + } - public async Task Checkout(BasketDTO basket) - { - var uri = API.Basket.CheckoutBasket(_basketByPassUrl); - var basketContent = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json"); + public async Task Checkout(BasketDTO basket) + { + var uri = API.Basket.CheckoutBasket(_basketByPassUrl); + var basketContent = new StringContent(JsonSerializer.Serialize(basket), System.Text.Encoding.UTF8, "application/json"); + + _logger.LogInformation("Uri chechout {uri}", uri); - _logger.LogInformation("Uri chechout {uri}", uri); + var response = await _apiClient.PostAsync(uri, basketContent); - var response = await _apiClient.PostAsync(uri, basketContent); + response.EnsureSuccessStatusCode(); + } - response.EnsureSuccessStatusCode(); - } + public async Task SetQuantities(ApplicationUser user, Dictionary quantities) + { + var uri = API.Purchase.UpdateBasketItem(_purchaseUrl); - public async Task SetQuantities(ApplicationUser user, Dictionary quantities) + var basketUpdate = new { - var uri = API.Purchase.UpdateBasketItem(_purchaseUrl); - - var basketUpdate = new + BasketId = user.Id, + Updates = quantities.Select(kvp => new { - BasketId = user.Id, - Updates = quantities.Select(kvp => new - { - BasketItemId = kvp.Key, - NewQty = kvp.Value - }).ToArray() - }; - - var basketContent = new StringContent(JsonConvert.SerializeObject(basketUpdate), System.Text.Encoding.UTF8, "application/json"); + BasketItemId = kvp.Key, + NewQty = kvp.Value + }).ToArray() + }; - var response = await _apiClient.PutAsync(uri, basketContent); + var basketContent = new StringContent(JsonSerializer.Serialize(basketUpdate), System.Text.Encoding.UTF8, "application/json"); - response.EnsureSuccessStatusCode(); + var response = await _apiClient.PutAsync(uri, basketContent); - var jsonResponse = await response.Content.ReadAsStringAsync(); + response.EnsureSuccessStatusCode(); - return JsonConvert.DeserializeObject(jsonResponse); - } + var jsonResponse = await response.Content.ReadAsStringAsync(); - public async Task GetOrderDraft(string basketId) + return JsonSerializer.Deserialize(jsonResponse, new JsonSerializerOptions { - var uri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId); - - var responseString = await _apiClient.GetStringAsync(uri); + PropertyNameCaseInsensitive = true + }); + } - var response = JsonConvert.DeserializeObject(responseString); + public async Task GetOrderDraft(string basketId) + { + var uri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId); - return response; - } + var responseString = await _apiClient.GetStringAsync(uri); - public async Task AddItemToBasket(ApplicationUser user, int productId) + var response = JsonSerializer.Deserialize(responseString, new JsonSerializerOptions { - var uri = API.Purchase.AddItemToBasket(_purchaseUrl); + PropertyNameCaseInsensitive = true + }); - var newItem = new - { - CatalogItemId = productId, - BasketId = user.Id, - Quantity = 1 - }; + return response; + } + + public async Task AddItemToBasket(ApplicationUser user, int productId) + { + var uri = API.Purchase.AddItemToBasket(_purchaseUrl); + + var newItem = new + { + CatalogItemId = productId, + BasketId = user.Id, + Quantity = 1 + }; - var basketContent = new StringContent(JsonConvert.SerializeObject(newItem), System.Text.Encoding.UTF8, "application/json"); + var basketContent = new StringContent(JsonSerializer.Serialize(newItem), System.Text.Encoding.UTF8, "application/json"); - var response = await _apiClient.PostAsync(uri, basketContent); - } + var response = await _apiClient.PostAsync(uri, basketContent); } } diff --git a/src/Web/WebMVC/Services/CatalogService.cs b/src/Web/WebMVC/Services/CatalogService.cs index 40d3644f4..96ad9c3c0 100644 --- a/src/Web/WebMVC/Services/CatalogService.cs +++ b/src/Web/WebMVC/Services/CatalogService.cs @@ -1,88 +1,80 @@ -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using WebMVC.Infrastructure; - -namespace Microsoft.eShopOnContainers.WebMVC.Services -{ - public class CatalogService : ICatalogService - { - private readonly IOptions _settings; - private readonly HttpClient _httpClient; - private readonly ILogger _logger; - - private readonly string _remoteServiceBaseUrl; +namespace Microsoft.eShopOnContainers.WebMVC.Services; - public CatalogService(HttpClient httpClient, ILogger logger, IOptions settings) - { - _httpClient = httpClient; - _settings = settings; - _logger = logger; +public class CatalogService : ICatalogService +{ + private readonly IOptions _settings; + private readonly HttpClient _httpClient; + private readonly ILogger _logger; - _remoteServiceBaseUrl = $"{_settings.Value.PurchaseUrl}/c/api/v1/catalog/"; - } + private readonly string _remoteServiceBaseUrl; - public async Task GetCatalogItems(int page, int take, int? brand, int? type) - { - var uri = API.Catalog.GetAllCatalogItems(_remoteServiceBaseUrl, page, take, brand, type); + public CatalogService(HttpClient httpClient, ILogger logger, IOptions settings) + { + _httpClient = httpClient; + _settings = settings; + _logger = logger; - var responseString = await _httpClient.GetStringAsync(uri); + _remoteServiceBaseUrl = $"{_settings.Value.PurchaseUrl}/c/api/v1/catalog/"; + } - var catalog = JsonConvert.DeserializeObject(responseString); + public async Task GetCatalogItems(int page, int take, int? brand, int? type) + { + var uri = API.Catalog.GetAllCatalogItems(_remoteServiceBaseUrl, page, take, brand, type); - return catalog; - } + var responseString = await _httpClient.GetStringAsync(uri); - public async Task> GetBrands() + var catalog = JsonSerializer.Deserialize(responseString, new JsonSerializerOptions { - var uri = API.Catalog.GetAllBrands(_remoteServiceBaseUrl); + PropertyNameCaseInsensitive = true + }); - var responseString = await _httpClient.GetStringAsync(uri); + return catalog; + } + + public async Task> GetBrands() + { + var uri = API.Catalog.GetAllBrands(_remoteServiceBaseUrl); - var items = new List(); + var responseString = await _httpClient.GetStringAsync(uri); - items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true }); + var items = new List(); - var brands = JArray.Parse(responseString); + items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true }); + + using var brands = JsonDocument.Parse(responseString); - foreach (var brand in brands.Children()) + foreach (JsonElement brand in brands.RootElement.EnumerateArray()) + { + items.Add(new SelectListItem() { - items.Add(new SelectListItem() - { - Value = brand.Value("id"), - Text = brand.Value("brand") - }); - } - - return items; + Value = brand.GetProperty("id").ToString(), + Text = brand.GetProperty("brand").ToString() + }); } - public async Task> GetTypes() - { - var uri = API.Catalog.GetAllTypes(_remoteServiceBaseUrl); + return items; + } + + public async Task> GetTypes() + { + var uri = API.Catalog.GetAllTypes(_remoteServiceBaseUrl); - var responseString = await _httpClient.GetStringAsync(uri); + var responseString = await _httpClient.GetStringAsync(uri); - var items = new List(); - items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true }); + var items = new List(); + items.Add(new SelectListItem() { Value = null, Text = "All", Selected = true }); + + using var catalogTypes = JsonDocument.Parse(responseString); - var brands = JArray.Parse(responseString); - foreach (var brand in brands.Children()) + foreach (JsonElement catalogType in catalogTypes.RootElement.EnumerateArray()) + { + items.Add(new SelectListItem() { - items.Add(new SelectListItem() - { - Value = brand.Value("id"), - Text = brand.Value("type") - }); - } - - return items; + Value = catalogType.GetProperty("id").ToString(), + Text = catalogType.GetProperty("type").ToString() + }); } + + return items; } } diff --git a/src/Web/WebMVC/Services/IBasketService.cs b/src/Web/WebMVC/Services/IBasketService.cs index cc576ec11..9ef09ac3a 100644 --- a/src/Web/WebMVC/Services/IBasketService.cs +++ b/src/Web/WebMVC/Services/IBasketService.cs @@ -1,17 +1,13 @@ -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System.Collections.Generic; -using System.Threading.Tasks; -using WebMVC.Services.ModelDTOs; +namespace Microsoft.eShopOnContainers.WebMVC.Services; -namespace Microsoft.eShopOnContainers.WebMVC.Services +using Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public interface IBasketService { - public interface IBasketService - { - Task GetBasket(ApplicationUser user); - Task AddItemToBasket(ApplicationUser user, int productId); - Task UpdateBasket(Basket basket); - Task Checkout(BasketDTO basket); - Task SetQuantities(ApplicationUser user, Dictionary quantities); - Task GetOrderDraft(string basketId); - } + Task GetBasket(ApplicationUser user); + Task AddItemToBasket(ApplicationUser user, int productId); + Task UpdateBasket(Basket basket); + Task Checkout(BasketDTO basket); + Task SetQuantities(ApplicationUser user, Dictionary quantities); + Task GetOrderDraft(string basketId); } diff --git a/src/Web/WebMVC/Services/ICatalogService.cs b/src/Web/WebMVC/Services/ICatalogService.cs index 3879ad13d..905ce9a18 100644 --- a/src/Web/WebMVC/Services/ICatalogService.cs +++ b/src/Web/WebMVC/Services/ICatalogService.cs @@ -1,14 +1,8 @@ -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System.Collections.Generic; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.WebMVC.Services; -namespace Microsoft.eShopOnContainers.WebMVC.Services +public interface ICatalogService { - public interface ICatalogService - { - Task GetCatalogItems(int page, int take, int? brand, int? type); - Task> GetBrands(); - Task> GetTypes(); - } + Task GetCatalogItems(int page, int take, int? brand, int? type); + Task> GetBrands(); + Task> GetTypes(); } diff --git a/src/Web/WebMVC/Services/IIdentityParser.cs b/src/Web/WebMVC/Services/IIdentityParser.cs index aaf2ab8cd..4625bb62f 100644 --- a/src/Web/WebMVC/Services/IIdentityParser.cs +++ b/src/Web/WebMVC/Services/IIdentityParser.cs @@ -1,9 +1,6 @@ -using System.Security.Principal; +namespace Microsoft.eShopOnContainers.WebMVC.Services; -namespace Microsoft.eShopOnContainers.WebMVC.Services +public interface IIdentityParser { - public interface IIdentityParser - { - T Parse(IPrincipal principal); - } + T Parse(IPrincipal principal); } diff --git a/src/Web/WebMVC/Services/IOrderingService.cs b/src/Web/WebMVC/Services/IOrderingService.cs index cc1968c53..2c34b7d01 100644 --- a/src/Web/WebMVC/Services/IOrderingService.cs +++ b/src/Web/WebMVC/Services/IOrderingService.cs @@ -1,18 +1,13 @@ -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System.Collections.Generic; -using System.Threading.Tasks; -using WebMVC.Services.ModelDTOs; +namespace Microsoft.eShopOnContainers.WebMVC.Services; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.Services +public interface IOrderingService { - public interface IOrderingService - { - Task> GetMyOrders(ApplicationUser user); - Task GetOrder(ApplicationUser user, string orderId); - Task CancelOrder(string orderId); - Task ShipOrder(string orderId); - Order MapUserInfoIntoOrder(ApplicationUser user, Order order); - BasketDTO MapOrderToBasket(Order order); - void OverrideUserInfoIntoOrder(Order original, Order destination); - } + Task> GetMyOrders(ApplicationUser user); + Task GetOrder(ApplicationUser user, string orderId); + Task CancelOrder(string orderId); + Task ShipOrder(string orderId); + Order MapUserInfoIntoOrder(ApplicationUser user, Order order); + BasketDTO MapOrderToBasket(Order order); + void OverrideUserInfoIntoOrder(Order original, Order destination); } diff --git a/src/Web/WebMVC/Services/IdentityParser.cs b/src/Web/WebMVC/Services/IdentityParser.cs index 5360ebed4..bb969312d 100644 --- a/src/Web/WebMVC/Services/IdentityParser.cs +++ b/src/Web/WebMVC/Services/IdentityParser.cs @@ -1,42 +1,33 @@ -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System; -using System.Linq; -using System.Security.Claims; -using System.Security.Principal; +namespace Microsoft.eShopOnContainers.WebMVC.Services; -namespace Microsoft.eShopOnContainers.WebMVC.Services +public class IdentityParser : IIdentityParser { - public class IdentityParser : IIdentityParser + public ApplicationUser Parse(IPrincipal principal) { - public ApplicationUser Parse(IPrincipal principal) + // Pattern matching 'is' expression + // assigns "claims" if "principal" is a "ClaimsPrincipal" + if (principal is ClaimsPrincipal claims) { - // Pattern matching 'is' expression - // assigns "claims" if "principal" is a "ClaimsPrincipal" - if (principal is ClaimsPrincipal claims) + return new ApplicationUser { - return new ApplicationUser - { - CardHolderName = claims.Claims.FirstOrDefault(x => x.Type == "card_holder")?.Value ?? "", - CardNumber = claims.Claims.FirstOrDefault(x => x.Type == "card_number")?.Value ?? "", - Expiration = claims.Claims.FirstOrDefault(x => x.Type == "card_expiration")?.Value ?? "", - CardType = int.Parse(claims.Claims.FirstOrDefault(x => x.Type == "missing")?.Value ?? "0"), - City = claims.Claims.FirstOrDefault(x => x.Type == "address_city")?.Value ?? "", - Country = claims.Claims.FirstOrDefault(x => x.Type == "address_country")?.Value ?? "", - Email = claims.Claims.FirstOrDefault(x => x.Type == "email")?.Value ?? "", - Id = claims.Claims.FirstOrDefault(x => x.Type == "sub")?.Value ?? "", - LastName = claims.Claims.FirstOrDefault(x => x.Type == "last_name")?.Value ?? "", - Name = claims.Claims.FirstOrDefault(x => x.Type == "name")?.Value ?? "", - PhoneNumber = claims.Claims.FirstOrDefault(x => x.Type == "phone_number")?.Value ?? "", - SecurityNumber = claims.Claims.FirstOrDefault(x => x.Type == "card_security_number")?.Value ?? "", - State = claims.Claims.FirstOrDefault(x => x.Type == "address_state")?.Value ?? "", - Street = claims.Claims.FirstOrDefault(x => x.Type == "address_street")?.Value ?? "", - ZipCode = claims.Claims.FirstOrDefault(x => x.Type == "address_zip_code")?.Value ?? "" - }; - } - throw new ArgumentException(message: "The principal must be a ClaimsPrincipal", paramName: nameof(principal)); + CardHolderName = claims.Claims.FirstOrDefault(x => x.Type == "card_holder")?.Value ?? "", + CardNumber = claims.Claims.FirstOrDefault(x => x.Type == "card_number")?.Value ?? "", + Expiration = claims.Claims.FirstOrDefault(x => x.Type == "card_expiration")?.Value ?? "", + CardType = int.Parse(claims.Claims.FirstOrDefault(x => x.Type == "missing")?.Value ?? "0"), + City = claims.Claims.FirstOrDefault(x => x.Type == "address_city")?.Value ?? "", + Country = claims.Claims.FirstOrDefault(x => x.Type == "address_country")?.Value ?? "", + Email = claims.Claims.FirstOrDefault(x => x.Type == "email")?.Value ?? "", + Id = claims.Claims.FirstOrDefault(x => x.Type == "sub")?.Value ?? "", + LastName = claims.Claims.FirstOrDefault(x => x.Type == "last_name")?.Value ?? "", + Name = claims.Claims.FirstOrDefault(x => x.Type == "name")?.Value ?? "", + PhoneNumber = claims.Claims.FirstOrDefault(x => x.Type == "phone_number")?.Value ?? "", + SecurityNumber = claims.Claims.FirstOrDefault(x => x.Type == "card_security_number")?.Value ?? "", + State = claims.Claims.FirstOrDefault(x => x.Type == "address_state")?.Value ?? "", + Street = claims.Claims.FirstOrDefault(x => x.Type == "address_street")?.Value ?? "", + ZipCode = claims.Claims.FirstOrDefault(x => x.Type == "address_zip_code")?.Value ?? "" + }; } + throw new ArgumentException(message: "The principal must be a ClaimsPrincipal", paramName: nameof(principal)); } } - - diff --git a/src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs b/src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs index 59b8ea2ca..c3d69656c 100644 --- a/src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs +++ b/src/Web/WebMVC/Services/ModelDTOs/BasketDTO.cs @@ -1,37 +1,32 @@ -using System; -using System.ComponentModel.DataAnnotations; +namespace WebMVC.Services.ModelDTOs; -namespace WebMVC.Services.ModelDTOs +public record BasketDTO { - public record BasketDTO - { - [Required] - public string City { get; init; } - [Required] - public string Street { get; init; } - [Required] - public string State { get; init; } - [Required] - public string Country { get; init; } + [Required] + public string City { get; init; } + [Required] + public string Street { get; init; } + [Required] + public string State { get; init; } + [Required] + public string Country { get; init; } - public string ZipCode { get; init; } - [Required] - public string CardNumber { get; init; } - [Required] - public string CardHolderName { get; init; } + public string ZipCode { get; init; } + [Required] + public string CardNumber { get; init; } + [Required] + public string CardHolderName { get; init; } - [Required] - public DateTime CardExpiration { get; init; } + [Required] + public DateTime CardExpiration { get; init; } - [Required] - public string CardSecurityNumber { get; init; } + [Required] + public string CardSecurityNumber { get; init; } - public int CardTypeId { get; init; } + public int CardTypeId { get; init; } - public string Buyer { get; init; } + public string Buyer { get; init; } - [Required] - public Guid RequestId { get; init; } - } + [Required] + public Guid RequestId { get; init; } } - diff --git a/src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs b/src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs index 626b2b2d3..2ac612284 100644 --- a/src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs +++ b/src/Web/WebMVC/Services/ModelDTOs/LocationDTO.cs @@ -1,8 +1,7 @@ -namespace WebMVC.Services.ModelDTOs +namespace WebMVC.Services.ModelDTOs; + +public record LocationDTO { - public record LocationDTO - { - public double Longitude { get; init; } - public double Latitude { get; init; } - } + public double Longitude { get; init; } + public double Latitude { get; init; } } diff --git a/src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs b/src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs index f88cf22f8..3a9de3c0f 100644 --- a/src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs +++ b/src/Web/WebMVC/Services/ModelDTOs/OrderDTO.cs @@ -1,10 +1,7 @@ -using System.ComponentModel.DataAnnotations; +namespace WebMVC.Services.ModelDTOs; -namespace WebMVC.Services.ModelDTOs +public record OrderDTO { - public record OrderDTO - { - [Required] - public string OrderNumber { get; init; } - } -} \ No newline at end of file + [Required] + public string OrderNumber { get; init; } +} diff --git a/src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs b/src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs index 34e4a2695..94d3f7939 100644 --- a/src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs +++ b/src/Web/WebMVC/Services/ModelDTOs/OrderProcessAction.cs @@ -1,20 +1,19 @@ -namespace WebMVC.Services.ModelDTOs +namespace WebMVC.Services.ModelDTOs; + +public record OrderProcessAction { - public record OrderProcessAction - { - public string Code { get; } - public string Name { get; } + public string Code { get; } + public string Name { get; } - public static OrderProcessAction Ship = new OrderProcessAction(nameof(Ship).ToLowerInvariant(), "Ship"); + public static OrderProcessAction Ship = new OrderProcessAction(nameof(Ship).ToLowerInvariant(), "Ship"); - protected OrderProcessAction() - { - } + protected OrderProcessAction() + { + } - public OrderProcessAction(string code, string name) - { - Code = code; - Name = name; - } + public OrderProcessAction(string code, string name) + { + Code = code; + Name = name; } } diff --git a/src/Web/WebMVC/Services/OrderingService.cs b/src/Web/WebMVC/Services/OrderingService.cs index b5ad13386..f1422c51f 100644 --- a/src/Web/WebMVC/Services/OrderingService.cs +++ b/src/Web/WebMVC/Services/OrderingService.cs @@ -1,143 +1,140 @@ -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Microsoft.Extensions.Options; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using WebMVC.Infrastructure; -using WebMVC.Services.ModelDTOs; - -namespace Microsoft.eShopOnContainers.WebMVC.Services -{ - public class OrderingService : IOrderingService - { - private HttpClient _httpClient; - private readonly string _remoteServiceBaseUrl; - private readonly IOptions _settings; +namespace Microsoft.eShopOnContainers.WebMVC.Services; +using Microsoft.eShopOnContainers.WebMVC.ViewModels; - public OrderingService(HttpClient httpClient, IOptions settings) - { - _httpClient = httpClient; - _settings = settings; +public class OrderingService : IOrderingService +{ + private HttpClient _httpClient; + private readonly string _remoteServiceBaseUrl; + private readonly IOptions _settings; - _remoteServiceBaseUrl = $"{settings.Value.PurchaseUrl}/o/api/v1/orders"; - } - async public Task GetOrder(ApplicationUser user, string id) - { - var uri = API.Order.GetOrder(_remoteServiceBaseUrl, id); + public OrderingService(HttpClient httpClient, IOptions settings) + { + _httpClient = httpClient; + _settings = settings; - var responseString = await _httpClient.GetStringAsync(uri); + _remoteServiceBaseUrl = $"{settings.Value.PurchaseUrl}/o/api/v1/orders"; + } - var response = JsonConvert.DeserializeObject(responseString); + async public Task GetOrder(ApplicationUser user, string id) + { + var uri = API.Order.GetOrder(_remoteServiceBaseUrl, id); - return response; - } + var responseString = await _httpClient.GetStringAsync(uri); - async public Task> GetMyOrders(ApplicationUser user) + var response = JsonSerializer.Deserialize(responseString, new JsonSerializerOptions { - var uri = API.Order.GetAllMyOrders(_remoteServiceBaseUrl); + PropertyNameCaseInsensitive = true + }); - var responseString = await _httpClient.GetStringAsync(uri); + return response; + } - var response = JsonConvert.DeserializeObject>(responseString); + async public Task> GetMyOrders(ApplicationUser user) + { + var uri = API.Order.GetAllMyOrders(_remoteServiceBaseUrl); - return response; - } + var responseString = await _httpClient.GetStringAsync(uri); + var response = JsonSerializer.Deserialize>(responseString, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + return response; + } - async public Task CancelOrder(string orderId) - { - var order = new OrderDTO() - { - OrderNumber = orderId - }; - var uri = API.Order.CancelOrder(_remoteServiceBaseUrl); - var orderContent = new StringContent(JsonConvert.SerializeObject(order), System.Text.Encoding.UTF8, "application/json"); - var response = await _httpClient.PutAsync(uri, orderContent); + async public Task CancelOrder(string orderId) + { + var order = new OrderDTO() + { + OrderNumber = orderId + }; - if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError) - { - throw new Exception("Error cancelling order, try later."); - } + var uri = API.Order.CancelOrder(_remoteServiceBaseUrl); + var orderContent = new StringContent(JsonSerializer.Serialize(order), System.Text.Encoding.UTF8, "application/json"); - response.EnsureSuccessStatusCode(); - } + var response = await _httpClient.PutAsync(uri, orderContent); - async public Task ShipOrder(string orderId) + if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError) { - var order = new OrderDTO() - { - OrderNumber = orderId - }; + throw new Exception("Error cancelling order, try later."); + } - var uri = API.Order.ShipOrder(_remoteServiceBaseUrl); - var orderContent = new StringContent(JsonConvert.SerializeObject(order), System.Text.Encoding.UTF8, "application/json"); + response.EnsureSuccessStatusCode(); + } - var response = await _httpClient.PutAsync(uri, orderContent); + async public Task ShipOrder(string orderId) + { + var order = new OrderDTO() + { + OrderNumber = orderId + }; - if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError) - { - throw new Exception("Error in ship order process, try later."); - } + var uri = API.Order.ShipOrder(_remoteServiceBaseUrl); + var orderContent = new StringContent(JsonSerializer.Serialize(order), System.Text.Encoding.UTF8, "application/json"); - response.EnsureSuccessStatusCode(); - } + var response = await _httpClient.PutAsync(uri, orderContent); - public void OverrideUserInfoIntoOrder(Order original, Order destination) + if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError) { - destination.City = original.City; - destination.Street = original.Street; - destination.State = original.State; - destination.Country = original.Country; - destination.ZipCode = original.ZipCode; - - destination.CardNumber = original.CardNumber; - destination.CardHolderName = original.CardHolderName; - destination.CardExpiration = original.CardExpiration; - destination.CardSecurityNumber = original.CardSecurityNumber; + throw new Exception("Error in ship order process, try later."); } - public Order MapUserInfoIntoOrder(ApplicationUser user, Order order) - { - order.City = user.City; - order.Street = user.Street; - order.State = user.State; - order.Country = user.Country; - order.ZipCode = user.ZipCode; - - order.CardNumber = user.CardNumber; - order.CardHolderName = user.CardHolderName; - order.CardExpiration = new DateTime(int.Parse("20" + user.Expiration.Split('/')[1]), int.Parse(user.Expiration.Split('/')[0]), 1); - order.CardSecurityNumber = user.SecurityNumber; - - return order; - } + response.EnsureSuccessStatusCode(); + } - public BasketDTO MapOrderToBasket(Order order) + public void OverrideUserInfoIntoOrder(Order original, Order destination) + { + destination.City = original.City; + destination.Street = original.Street; + destination.State = original.State; + destination.Country = original.Country; + destination.ZipCode = original.ZipCode; + + destination.CardNumber = original.CardNumber; + destination.CardHolderName = original.CardHolderName; + destination.CardExpiration = original.CardExpiration; + destination.CardSecurityNumber = original.CardSecurityNumber; + } + + public Order MapUserInfoIntoOrder(ApplicationUser user, Order order) + { + order.City = user.City; + order.Street = user.Street; + order.State = user.State; + order.Country = user.Country; + order.ZipCode = user.ZipCode; + + order.CardNumber = user.CardNumber; + order.CardHolderName = user.CardHolderName; + order.CardExpiration = new DateTime(int.Parse("20" + user.Expiration.Split('/')[1]), int.Parse(user.Expiration.Split('/')[0]), 1); + order.CardSecurityNumber = user.SecurityNumber; + + return order; + } + + public BasketDTO MapOrderToBasket(Order order) + { + order.CardExpirationApiFormat(); + + return new BasketDTO() { - order.CardExpirationApiFormat(); - - return new BasketDTO() - { - City = order.City, - Street = order.Street, - State = order.State, - Country = order.Country, - ZipCode = order.ZipCode, - CardNumber = order.CardNumber, - CardHolderName = order.CardHolderName, - CardExpiration = order.CardExpiration, - CardSecurityNumber = order.CardSecurityNumber, - CardTypeId = 1, - Buyer = order.Buyer, - RequestId = order.RequestId - }; - } + City = order.City, + Street = order.Street, + State = order.State, + Country = order.Country, + ZipCode = order.ZipCode, + CardNumber = order.CardNumber, + CardHolderName = order.CardHolderName, + CardExpiration = order.CardExpiration, + CardSecurityNumber = order.CardSecurityNumber, + CardTypeId = 1, + Buyer = order.Buyer, + RequestId = order.RequestId + }; } } diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs index 427e234c7..405d2ced4 100644 --- a/src/Web/WebMVC/Startup.cs +++ b/src/Web/WebMVC/Startup.cs @@ -1,212 +1,190 @@ -using Devspaces.Support; -using HealthChecks.UI.Client; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.IdentityModel.Logging; -using StackExchange.Redis; -using System; -using System.IdentityModel.Tokens.Jwt; -using WebMVC.Infrastructure; - -namespace Microsoft.eShopOnContainers.WebMVC +namespace Microsoft.eShopOnContainers.WebMVC; + +public class Startup { - public class Startup + public Startup(IConfiguration configuration) { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } + Configuration = configuration; + } - public IConfiguration Configuration { get; } + public IConfiguration Configuration { get; } - // This method gets called by the runtime. Use this method to add services to the IoC container. - public void ConfigureServices(IServiceCollection services) - { - services.AddControllersWithViews() - .Services - .AddAppInsight(Configuration) - .AddHealthChecks(Configuration) - .AddCustomMvc(Configuration) - .AddDevspaces() - .AddHttpClientServices(Configuration); + // This method gets called by the runtime. Use this method to add services to the IoC container. + public void ConfigureServices(IServiceCollection services) + { + services.AddControllersWithViews() + .Services + .AddAppInsight(Configuration) + .AddHealthChecks(Configuration) + .AddCustomMvc(Configuration) + .AddDevspaces() + .AddHttpClientServices(Configuration); - IdentityModelEventSource.ShowPII = true; // Caution! Do NOT use in production: https://aka.ms/IdentityModel/PII + IdentityModelEventSource.ShowPII = true; // Caution! Do NOT use in production: https://aka.ms/IdentityModel/PII - services.AddControllers(); + services.AddControllers(); - services.AddCustomAuthentication(Configuration); - } + services.AddCustomAuthentication(Configuration); + } - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + if (env.IsDevelopment()) { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - } + app.UseDeveloperExceptionPage(); + } + else + { + app.UseExceptionHandler("/Error"); + } - var pathBase = Configuration["PATH_BASE"]; + var pathBase = Configuration["PATH_BASE"]; - if (!string.IsNullOrEmpty(pathBase)) - { - app.UsePathBase(pathBase); - } + if (!string.IsNullOrEmpty(pathBase)) + { + app.UsePathBase(pathBase); + } - app.UseStaticFiles(); - app.UseSession(); + app.UseStaticFiles(); + app.UseSession(); - WebContextSeed.Seed(app, env); + WebContextSeed.Seed(app, env); - // Fix samesite issue when running eShop from docker-compose locally as by default http protocol is being used - // Refer to https://github.com/dotnet-architecture/eShopOnContainers/issues/1391 - app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = AspNetCore.Http.SameSiteMode.Lax }); + // Fix samesite issue when running eShop from docker-compose locally as by default http protocol is being used + // Refer to https://github.com/dotnet-architecture/eShopOnContainers/issues/1391 + app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = AspNetCore.Http.SameSiteMode.Lax }); - app.UseRouting(); + app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); + app.UseAuthentication(); + app.UseAuthorization(); - app.UseEndpoints(endpoints => + app.UseEndpoints(endpoints => + { + endpoints.MapControllerRoute("default", "{controller=Catalog}/{action=Index}/{id?}"); + endpoints.MapControllerRoute("defaultError", "{controller=Error}/{action=Error}"); + endpoints.MapControllers(); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions { - endpoints.MapControllerRoute("default", "{controller=Catalog}/{action=Index}/{id?}"); - endpoints.MapControllerRoute("defaultError", "{controller=Error}/{action=Error}"); - endpoints.MapControllers(); - endpoints.MapHealthChecks("/liveness", new HealthCheckOptions - { - Predicate = r => r.Name.Contains("self") - }); - endpoints.MapHealthChecks("/hc", new HealthCheckOptions() - { - Predicate = _ => true, - ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse - }); + Predicate = r => r.Name.Contains("self") }); - } + endpoints.MapHealthChecks("/hc", new HealthCheckOptions() + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + }); } +} + +static class ServiceCollectionExtensions +{ - static class ServiceCollectionExtensions + public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) { + services.AddApplicationInsightsTelemetry(configuration); + services.AddApplicationInsightsKubernetesEnricher(); - public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) - { - services.AddApplicationInsightsTelemetry(configuration); - services.AddApplicationInsightsKubernetesEnricher(); + return services; + } - return services; - } + public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) + { + services.AddHealthChecks() + .AddCheck("self", () => HealthCheckResult.Healthy()) + .AddUrlGroup(new Uri(configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }); - public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) - { - services.AddHealthChecks() - .AddCheck("self", () => HealthCheckResult.Healthy()) - .AddUrlGroup(new Uri(configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }); + return services; + } - return services; - } + public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + services.Configure(configuration); + services.AddSession(); + services.AddDistributedMemoryCache(); - public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) + if (configuration.GetValue("IsClusterEnv") == bool.TrueString) { - services.AddOptions(); - services.Configure(configuration); - services.AddSession(); - services.AddDistributedMemoryCache(); - - if (configuration.GetValue("IsClusterEnv") == bool.TrueString) + services.AddDataProtection(opts => { - services.AddDataProtection(opts => - { - opts.ApplicationDiscriminator = "eshop.webmvc"; - }) - .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys"); - } - - return services; + opts.ApplicationDiscriminator = "eshop.webmvc"; + }) + .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys"); } - // Adds all Http client services - public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) - { - services.AddSingleton(); + return services; + } - //register delegating handlers - services.AddTransient(); - services.AddTransient(); + // Adds all Http client services + public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) + { + services.AddSingleton(); - //set 5 min as the lifetime for each HttpMessageHandler int the pool - services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5)).AddDevspacesSupport(); + //register delegating handlers + services.AddTransient(); + services.AddTransient(); - //add http client services - services.AddHttpClient() - .SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes - .AddHttpMessageHandler() - .AddDevspacesSupport(); + //set 5 min as the lifetime for each HttpMessageHandler int the pool + services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(TimeSpan.FromMinutes(5)).AddDevspacesSupport(); - services.AddHttpClient() - .AddDevspacesSupport(); + //add http client services + services.AddHttpClient() + .SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes + .AddHttpMessageHandler() + .AddDevspacesSupport(); - services.AddHttpClient() - .AddHttpMessageHandler() - .AddHttpMessageHandler() - .AddDevspacesSupport(); + services.AddHttpClient() + .AddDevspacesSupport(); + services.AddHttpClient() + .AddHttpMessageHandler() + .AddHttpMessageHandler() + .AddDevspacesSupport(); - //add custom application services - services.AddTransient, IdentityParser>(); - return services; - } + //add custom application services + services.AddTransient, IdentityParser>(); + return services; + } - public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) - { - var identityUrl = configuration.GetValue("IdentityUrl"); - var callBackUrl = configuration.GetValue("CallBackUrl"); - var sessionCookieLifetime = configuration.GetValue("SessionCookieLifetimeMinutes", 60); - // Add Authentication services + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + var identityUrl = configuration.GetValue("IdentityUrl"); + var callBackUrl = configuration.GetValue("CallBackUrl"); + var sessionCookieLifetime = configuration.GetValue("SessionCookieLifetimeMinutes", 60); - services.AddAuthentication(options => - { - options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }) - .AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime)) - .AddOpenIdConnect(options => - { - options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; - options.Authority = identityUrl.ToString(); - options.SignedOutRedirectUri = callBackUrl.ToString(); - options.ClientId = "mvc"; - options.ClientSecret = "secret"; - options.ResponseType = "code id_token"; - options.SaveTokens = true; - options.GetClaimsFromUserInfoEndpoint = true; - options.RequireHttpsMetadata = false; - options.Scope.Add("openid"); - options.Scope.Add("profile"); - options.Scope.Add("orders"); - options.Scope.Add("basket"); - options.Scope.Add("webshoppingagg"); - options.Scope.Add("orders.signalrhub"); - }); + // Add Authentication services - return services; - } + services.AddAuthentication(options => + { + options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + }) + .AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime)) + .AddOpenIdConnect(options => + { + options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; + options.Authority = identityUrl.ToString(); + options.SignedOutRedirectUri = callBackUrl.ToString(); + options.ClientId = "mvc"; + options.ClientSecret = "secret"; + options.ResponseType = "code id_token"; + options.SaveTokens = true; + options.GetClaimsFromUserInfoEndpoint = true; + options.RequireHttpsMetadata = false; + options.Scope.Add("openid"); + options.Scope.Add("profile"); + options.Scope.Add("orders"); + options.Scope.Add("basket"); + options.Scope.Add("webshoppingagg"); + options.Scope.Add("orders.signalrhub"); + }); + + return services; } } diff --git a/src/Web/WebMVC/ViewComponents/Cart.cs b/src/Web/WebMVC/ViewComponents/Cart.cs index 0fa004a49..8ec80fa91 100644 --- a/src/Web/WebMVC/ViewComponents/Cart.cs +++ b/src/Web/WebMVC/ViewComponents/Cart.cs @@ -1,37 +1,30 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using Microsoft.eShopOnContainers.WebMVC.ViewModels.CartViewModels; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents; -namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents +public class Cart : ViewComponent { - public class Cart : ViewComponent - { - private readonly IBasketService _cartSvc; + private readonly IBasketService _cartSvc; - public Cart(IBasketService cartSvc) => _cartSvc = cartSvc; + public Cart(IBasketService cartSvc) => _cartSvc = cartSvc; - public async Task InvokeAsync(ApplicationUser user) + public async Task InvokeAsync(ApplicationUser user) + { + var vm = new CartComponentViewModel(); + try { - var vm = new CartComponentViewModel(); - try - { - var itemsInCart = await ItemsInCartAsync(user); - vm.ItemsCount = itemsInCart; - return View(vm); - } - catch - { - ViewBag.IsBasketInoperative = true; - } - + var itemsInCart = await ItemsInCartAsync(user); + vm.ItemsCount = itemsInCart; return View(vm); } - private async Task ItemsInCartAsync(ApplicationUser user) + catch { - var basket = await _cartSvc.GetBasket(user); - return basket.Items.Count; + ViewBag.IsBasketInoperative = true; } + + return View(vm); + } + private async Task ItemsInCartAsync(ApplicationUser user) + { + var basket = await _cartSvc.GetBasket(user); + return basket.Items.Count; } } diff --git a/src/Web/WebMVC/ViewComponents/CartList.cs b/src/Web/WebMVC/ViewComponents/CartList.cs index f572c8437..469fc4f4b 100644 --- a/src/Web/WebMVC/ViewComponents/CartList.cs +++ b/src/Web/WebMVC/ViewComponents/CartList.cs @@ -1,33 +1,26 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.eShopOnContainers.WebMVC.Services; -using Microsoft.eShopOnContainers.WebMVC.ViewModels; -using System; -using System.Threading.Tasks; +namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents; -namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents +public class CartList : ViewComponent { - public class CartList : ViewComponent - { - private readonly IBasketService _cartSvc; + private readonly IBasketService _cartSvc; - public CartList(IBasketService cartSvc) => _cartSvc = cartSvc; + public CartList(IBasketService cartSvc) => _cartSvc = cartSvc; - public async Task InvokeAsync(ApplicationUser user) + public async Task InvokeAsync(ApplicationUser user) + { + var vm = new Basket(); + try { - var vm = new Basket(); - try - { - vm = await GetItemsAsync(user); - return View(vm); - } - catch (Exception ex) - { - ViewBag.BasketInoperativeMsg = $"Basket Service is inoperative, please try later on. ({ex.GetType().Name} - {ex.Message}))"; - } - + vm = await GetItemsAsync(user); return View(vm); } + catch (Exception ex) + { + ViewBag.BasketInoperativeMsg = $"Basket Service is inoperative, please try later on. ({ex.GetType().Name} - {ex.Message}))"; + } - private Task GetItemsAsync(ApplicationUser user) => _cartSvc.GetBasket(user); + return View(vm); } + + private Task GetItemsAsync(ApplicationUser user) => _cartSvc.GetBasket(user); } diff --git a/src/Web/WebMVC/ViewModels/Annotations/CardExpiration.cs b/src/Web/WebMVC/ViewModels/Annotations/CardExpiration.cs index 3819f6fb0..52c6376d3 100644 --- a/src/Web/WebMVC/ViewModels/Annotations/CardExpiration.cs +++ b/src/Web/WebMVC/ViewModels/Annotations/CardExpiration.cs @@ -1,31 +1,27 @@ -using System; -using System.ComponentModel.DataAnnotations; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Annotations; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Annotations +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] +public class CardExpirationAttribute : ValidationAttribute { - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] - public class CardExpirationAttribute : ValidationAttribute + public override bool IsValid(object value) { - public override bool IsValid(object value) - { - if (value == null) - return false; + if (value == null) + return false; - var monthString = value.ToString().Split('/')[0]; - var yearString = $"20{value.ToString().Split('/')[1]}"; - // Use the 'out' variable initializer to simplify - // the logic of validating the expiration date - if ((int.TryParse(monthString, out var month)) && - (int.TryParse(yearString, out var year))) - { - DateTime d = new DateTime(year, month, 1); + var monthString = value.ToString().Split('/')[0]; + var yearString = $"20{value.ToString().Split('/')[1]}"; + // Use the 'out' variable initializer to simplify + // the logic of validating the expiration date + if ((int.TryParse(monthString, out var month)) && + (int.TryParse(yearString, out var year))) + { + DateTime d = new DateTime(year, month, 1); - return d > DateTime.UtcNow; - } - else - { - return false; - } + return d > DateTime.UtcNow; + } + else + { + return false; } } } diff --git a/src/Web/WebMVC/ViewModels/Annotations/LatitudeCoordinate.cs b/src/Web/WebMVC/ViewModels/Annotations/LatitudeCoordinate.cs index 5731b8895..dbdf65662 100644 --- a/src/Web/WebMVC/ViewModels/Annotations/LatitudeCoordinate.cs +++ b/src/Web/WebMVC/ViewModels/Annotations/LatitudeCoordinate.cs @@ -1,22 +1,18 @@ -using System; -using System.ComponentModel.DataAnnotations; +namespace WebMVC.ViewModels.Annotations; -namespace WebMVC.ViewModels.Annotations +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] +public class LatitudeCoordinate : ValidationAttribute { - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] - public class LatitudeCoordinate : ValidationAttribute + protected override ValidationResult + IsValid(object value, ValidationContext validationContext) { - protected override ValidationResult - IsValid(object value, ValidationContext validationContext) + double coordinate; + if (!double.TryParse(value.ToString(), out coordinate) || (coordinate < -90 || coordinate > 90)) { - double coordinate; - if (!double.TryParse(value.ToString(), out coordinate) || (coordinate < -90 || coordinate > 90)) - { - return new ValidationResult - ("Latitude must be between -90 and 90 degrees inclusive."); - } - - return ValidationResult.Success; + return new ValidationResult + ("Latitude must be between -90 and 90 degrees inclusive."); } + + return ValidationResult.Success; } } diff --git a/src/Web/WebMVC/ViewModels/Annotations/LongitudeCoordinate.cs b/src/Web/WebMVC/ViewModels/Annotations/LongitudeCoordinate.cs index de1f5cd3e..f0c0dbb32 100644 --- a/src/Web/WebMVC/ViewModels/Annotations/LongitudeCoordinate.cs +++ b/src/Web/WebMVC/ViewModels/Annotations/LongitudeCoordinate.cs @@ -1,22 +1,18 @@ -using System; -using System.ComponentModel.DataAnnotations; +namespace WebMVC.ViewModels.Annotations; -namespace WebMVC.ViewModels.Annotations +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] +public class LongitudeCoordinate : ValidationAttribute { - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] - public class LongitudeCoordinate : ValidationAttribute + protected override ValidationResult + IsValid(object value, ValidationContext validationContext) { - protected override ValidationResult - IsValid(object value, ValidationContext validationContext) + double coordinate; + if (!double.TryParse(value.ToString(), out coordinate) || (coordinate < -180 || coordinate > 180)) { - double coordinate; - if (!double.TryParse(value.ToString(), out coordinate) || (coordinate < -180 || coordinate > 180)) - { - return new ValidationResult - ("Longitude must be between -180 and 180 degrees inclusive."); - } - - return ValidationResult.Success; + return new ValidationResult + ("Longitude must be between -180 and 180 degrees inclusive."); } + + return ValidationResult.Success; } } diff --git a/src/Web/WebMVC/ViewModels/ApplicationUser.cs b/src/Web/WebMVC/ViewModels/ApplicationUser.cs index ec0318850..a8473c7e8 100644 --- a/src/Web/WebMVC/ViewModels/ApplicationUser.cs +++ b/src/Web/WebMVC/ViewModels/ApplicationUser.cs @@ -1,28 +1,24 @@ -using Microsoft.AspNetCore.Identity; -using System.ComponentModel.DataAnnotations; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +// Add profile data for application users by adding properties to the ApplicationUser class +public class ApplicationUser : IdentityUser { - // Add profile data for application users by adding properties to the ApplicationUser class - public class ApplicationUser : IdentityUser - { - public string CardNumber { get; set; } - public string SecurityNumber { get; set; } - public string Expiration { get; set; } - public string CardHolderName { get; set; } - public int CardType { get; set; } - public string Street { get; set; } - public string City { get; set; } - public string State { get; set; } - public string StateCode { get; set; } - public string Country { get; set; } - public string CountryCode { get; set; } - public string ZipCode { get; set; } - public double Latitude { get; set; } - public double Longitude { get; set; } - [Required] - public string Name { get; set; } - [Required] - public string LastName { get; set; } - } + public string CardNumber { get; set; } + public string SecurityNumber { get; set; } + public string Expiration { get; set; } + public string CardHolderName { get; set; } + public int CardType { get; set; } + public string Street { get; set; } + public string City { get; set; } + public string State { get; set; } + public string StateCode { get; set; } + public string Country { get; set; } + public string CountryCode { get; set; } + public string ZipCode { get; set; } + public double Latitude { get; set; } + public double Longitude { get; set; } + [Required] + public string Name { get; set; } + [Required] + public string LastName { get; set; } } diff --git a/src/Web/WebMVC/ViewModels/Basket.cs b/src/Web/WebMVC/ViewModels/Basket.cs index 24c4ca30b..8369b7cc7 100644 --- a/src/Web/WebMVC/ViewModels/Basket.cs +++ b/src/Web/WebMVC/ViewModels/Basket.cs @@ -1,21 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +public record Basket { - public record Basket - { - // Use property initializer syntax. - // While this is often more useful for read only - // auto implemented properties, it can simplify logic - // for read/write properties. - public List Items { get; init; } = new List(); - public string BuyerId { get; init; } + // Use property initializer syntax. + // While this is often more useful for read only + // auto implemented properties, it can simplify logic + // for read/write properties. + public List Items { get; init; } = new List(); + public string BuyerId { get; init; } - public decimal Total() - { - return Math.Round(Items.Sum(x => x.UnitPrice * x.Quantity), 2); - } + public decimal Total() + { + return Math.Round(Items.Sum(x => x.UnitPrice * x.Quantity), 2); } } diff --git a/src/Web/WebMVC/ViewModels/BasketItem.cs b/src/Web/WebMVC/ViewModels/BasketItem.cs index 115871f96..faf503be0 100644 --- a/src/Web/WebMVC/ViewModels/BasketItem.cs +++ b/src/Web/WebMVC/ViewModels/BasketItem.cs @@ -1,13 +1,12 @@ -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public record BasketItem { - public record BasketItem - { - public string Id { get; init; } - public string ProductId { get; init; } - public string ProductName { get; init; } - public decimal UnitPrice { get; init; } - public decimal OldUnitPrice { get; init; } - public int Quantity { get; init; } - public string PictureUrl { get; init; } - } + public string Id { get; init; } + public int ProductId { get; init; } + public string ProductName { get; init; } + public decimal UnitPrice { get; init; } + public decimal OldUnitPrice { get; init; } + public int Quantity { get; init; } + public string PictureUrl { get; init; } } diff --git a/src/Web/WebMVC/ViewModels/Campaign.cs b/src/Web/WebMVC/ViewModels/Campaign.cs index eae64c39c..5a295e3a2 100644 --- a/src/Web/WebMVC/ViewModels/Campaign.cs +++ b/src/Web/WebMVC/ViewModels/Campaign.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +public record Campaign { - public record Campaign - { - public int PageIndex { get; init; } - public int PageSize { get; init; } - public int Count { get; init; } - public List Data { get; init; } - } -} \ No newline at end of file + public int PageIndex { get; init; } + public int PageSize { get; init; } + public int Count { get; init; } + public List Data { get; init; } +} diff --git a/src/Web/WebMVC/ViewModels/CampaignItem.cs b/src/Web/WebMVC/ViewModels/CampaignItem.cs index df5639fc2..6fd07b501 100644 --- a/src/Web/WebMVC/ViewModels/CampaignItem.cs +++ b/src/Web/WebMVC/ViewModels/CampaignItem.cs @@ -1,20 +1,17 @@ -using System; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +public record CampaignItem { - public record CampaignItem - { - public int Id { get; init; } + public int Id { get; init; } - public string Name { get; init; } + public string Name { get; init; } - public string Description { get; init; } + public string Description { get; init; } - public DateTime From { get; init; } + public DateTime From { get; init; } - public DateTime To { get; init; } + public DateTime To { get; init; } - public string PictureUri { get; init; } - public string DetailsUri { get; init; } - } -} \ No newline at end of file + public string PictureUri { get; init; } + public string DetailsUri { get; init; } +} diff --git a/src/Web/WebMVC/ViewModels/CartViewModels/IndexViewModel.cs b/src/Web/WebMVC/ViewModels/CartViewModels/IndexViewModel.cs index be7d6dd1f..cc7312f3e 100644 --- a/src/Web/WebMVC/ViewModels/CartViewModels/IndexViewModel.cs +++ b/src/Web/WebMVC/ViewModels/CartViewModels/IndexViewModel.cs @@ -1,8 +1,7 @@ -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.CartViewModels +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.CartViewModels; + +public class CartComponentViewModel { - public class CartComponentViewModel - { - public int ItemsCount { get; set; } - public string Disabled => (ItemsCount == 0) ? "is-disabled" : ""; - } + public int ItemsCount { get; set; } + public string Disabled => (ItemsCount == 0) ? "is-disabled" : ""; } diff --git a/src/Web/WebMVC/ViewModels/Catalog.cs b/src/Web/WebMVC/ViewModels/Catalog.cs index 60a9cc506..8851982c0 100644 --- a/src/Web/WebMVC/ViewModels/Catalog.cs +++ b/src/Web/WebMVC/ViewModels/Catalog.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +public record Catalog { - public record Catalog - { - public int PageIndex { get; init; } - public int PageSize { get; init; } - public int Count { get; init; } - public List Data { get; init; } - } + public int PageIndex { get; init; } + public int PageSize { get; init; } + public int Count { get; init; } + public List Data { get; init; } } diff --git a/src/Web/WebMVC/ViewModels/CatalogItem.cs b/src/Web/WebMVC/ViewModels/CatalogItem.cs index 7663fdf5c..2576da08b 100644 --- a/src/Web/WebMVC/ViewModels/CatalogItem.cs +++ b/src/Web/WebMVC/ViewModels/CatalogItem.cs @@ -1,15 +1,14 @@ -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public record CatalogItem { - public record CatalogItem - { - public int Id { get; init; } - public string Name { get; init; } - public string Description { get; init; } - public decimal Price { get; init; } - public string PictureUri { get; init; } - public int CatalogBrandId { get; init; } - public string CatalogBrand { get; init; } - public int CatalogTypeId { get; init; } - public string CatalogType { get; init; } - } -} \ No newline at end of file + public int Id { get; init; } + public string Name { get; init; } + public string Description { get; init; } + public decimal Price { get; init; } + public string PictureUri { get; init; } + public int CatalogBrandId { get; init; } + public string CatalogBrand { get; init; } + public int CatalogTypeId { get; init; } + public string CatalogType { get; init; } +} diff --git a/src/Web/WebMVC/ViewModels/CatalogViewModels/IndexViewModel.cs b/src/Web/WebMVC/ViewModels/CatalogViewModels/IndexViewModel.cs index 8f70b32d9..7ebe6f37f 100644 --- a/src/Web/WebMVC/ViewModels/CatalogViewModels/IndexViewModel.cs +++ b/src/Web/WebMVC/ViewModels/CatalogViewModels/IndexViewModel.cs @@ -1,16 +1,11 @@ -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination; -using System.Collections.Generic; +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels; -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels +public class IndexViewModel { - public class IndexViewModel - { - public IEnumerable CatalogItems { get; set; } - public IEnumerable Brands { get; set; } - public IEnumerable Types { get; set; } - public int? BrandFilterApplied { get; set; } - public int? TypesFilterApplied { get; set; } - public PaginationInfo PaginationInfo { get; set; } - } + public IEnumerable CatalogItems { get; set; } + public IEnumerable Brands { get; set; } + public IEnumerable Types { get; set; } + public int? BrandFilterApplied { get; set; } + public int? TypesFilterApplied { get; set; } + public PaginationInfo PaginationInfo { get; set; } } diff --git a/src/Web/WebMVC/ViewModels/Converters/NumberToStringConverter.cs b/src/Web/WebMVC/ViewModels/Converters/NumberToStringConverter.cs new file mode 100644 index 000000000..43a445c30 --- /dev/null +++ b/src/Web/WebMVC/ViewModels/Converters/NumberToStringConverter.cs @@ -0,0 +1,26 @@ +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public class NumberToStringConverter : JsonConverter +{ + public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Number) + { + var numberValue = reader.GetInt32(); + return numberValue.ToString(); + } + else if (reader.TokenType == JsonTokenType.String) + { + return reader.GetString(); + } + else + { + throw new JsonException(); + } + } + + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + { + writer.WriteStringValue(value); + } +} diff --git a/src/Web/WebMVC/ViewModels/Header.cs b/src/Web/WebMVC/ViewModels/Header.cs index ba1126fad..f3bb8f8a6 100644 --- a/src/Web/WebMVC/ViewModels/Header.cs +++ b/src/Web/WebMVC/ViewModels/Header.cs @@ -1,8 +1,7 @@ -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public record Header { - public record Header - { - public string Controller { get; init; } - public string Text { get; init; } - } -} \ No newline at end of file + public string Controller { get; init; } + public string Text { get; init; } +} diff --git a/src/Web/WebMVC/ViewModels/Order.cs b/src/Web/WebMVC/ViewModels/Order.cs index 4de37ca00..af358336a 100644 --- a/src/Web/WebMVC/ViewModels/Order.cs +++ b/src/Web/WebMVC/ViewModels/Order.cs @@ -1,103 +1,91 @@ -using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.eShopOnContainers.WebMVC.ViewModels.Annotations; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.ComponentModel.DataAnnotations; -using WebMVC.Services.ModelDTOs; - -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels -{ - public class Order - { - public string OrderNumber { get; set; } +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; - public DateTime Date { get; set; } +public class Order +{ + [JsonConverter(typeof(NumberToStringConverter))] + public string OrderNumber { get; set; } - public string Status { get; set; } + public DateTime Date { get; set; } - public decimal Total { get; set; } + public string Status { get; set; } - public string Description { get; set; } + public decimal Total { get; set; } - [Required] - public string City { get; set; } - [Required] - public string Street { get; set; } - [Required] - public string State { get; set; } - [Required] - public string Country { get; set; } + public string Description { get; set; } - public string ZipCode { get; set; } - [Required] - [DisplayName("Card number")] - public string CardNumber { get; set; } - [Required] - [DisplayName("Cardholder name")] - public string CardHolderName { get; set; } + [Required] + public string City { get; set; } + [Required] + public string Street { get; set; } + [Required] + public string State { get; set; } + [Required] + public string Country { get; set; } - public DateTime CardExpiration { get; set; } - [RegularExpression(@"(0[1-9]|1[0-2])\/[0-9]{2}", ErrorMessage = "Expiration should match a valid MM/YY value")] - [CardExpiration(ErrorMessage = "The card is expired"), Required] - [DisplayName("Card expiration")] - public string CardExpirationShort { get; set; } - [Required] - [DisplayName("Card security number")] - public string CardSecurityNumber { get; set; } + public string ZipCode { get; set; } + [Required] + [DisplayName("Card number")] + public string CardNumber { get; set; } + [Required] + [DisplayName("Cardholder name")] + public string CardHolderName { get; set; } - public int CardTypeId { get; set; } + public DateTime CardExpiration { get; set; } + [RegularExpression(@"(0[1-9]|1[0-2])\/[0-9]{2}", ErrorMessage = "Expiration should match a valid MM/YY value")] + [CardExpiration(ErrorMessage = "The card is expired"), Required] + [DisplayName("Card expiration")] + public string CardExpirationShort { get; set; } + [Required] + [DisplayName("Card security number")] + public string CardSecurityNumber { get; set; } - public string Buyer { get; set; } + public int CardTypeId { get; set; } - public List ActionCodeSelectList => - GetActionCodesByCurrentState(); + public string Buyer { get; set; } - // See the property initializer syntax below. This - // initializes the compiler generated field for this - // auto-implemented property. - public List OrderItems { get; } = new List(); + public List ActionCodeSelectList => + GetActionCodesByCurrentState(); + + public List OrderItems { get; set; } - [Required] - public Guid RequestId { get; set; } + [Required] + public Guid RequestId { get; set; } - public void CardExpirationShortFormat() - { - CardExpirationShort = CardExpiration.ToString("MM/yy"); - } + public void CardExpirationShortFormat() + { + CardExpirationShort = CardExpiration.ToString("MM/yy"); + } - public void CardExpirationApiFormat() - { - var month = CardExpirationShort.Split('/')[0]; - var year = $"20{CardExpirationShort.Split('/')[1]}"; + public void CardExpirationApiFormat() + { + var month = CardExpirationShort.Split('/')[0]; + var year = $"20{CardExpirationShort.Split('/')[1]}"; - CardExpiration = new DateTime(int.Parse(year), int.Parse(month), 1); - } + CardExpiration = new DateTime(int.Parse(year), int.Parse(month), 1); + } - private List GetActionCodesByCurrentState() + private List GetActionCodesByCurrentState() + { + var actions = new List(); + switch (Status?.ToLower()) { - var actions = new List(); - switch (Status?.ToLower()) - { - case "paid": - actions.Add(OrderProcessAction.Ship); - break; - } - - var result = new List(); - actions.ForEach(action => - { - result.Add(new SelectListItem { Text = action.Name, Value = action.Code }); - }); - - return result; + case "paid": + actions.Add(OrderProcessAction.Ship); + break; } - } - public enum CardType - { - AMEX = 1 + var result = new List(); + actions.ForEach(action => + { + result.Add(new SelectListItem { Text = action.Name, Value = action.Code }); + }); + + return result; } } + +public enum CardType +{ + AMEX = 1 +} diff --git a/src/Web/WebMVC/ViewModels/OrderItem.cs b/src/Web/WebMVC/ViewModels/OrderItem.cs index c63dcc988..05b2960f6 100644 --- a/src/Web/WebMVC/ViewModels/OrderItem.cs +++ b/src/Web/WebMVC/ViewModels/OrderItem.cs @@ -1,17 +1,16 @@ -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels; + +public record OrderItem { - public record OrderItem - { - public int ProductId { get; init; } + public int ProductId { get; init; } - public string ProductName { get; init; } + public string ProductName { get; init; } - public decimal UnitPrice { get; init; } + public decimal UnitPrice { get; init; } - public decimal Discount { get; init; } + public decimal Discount { get; init; } - public int Units { get; init; } + public int Units { get; init; } - public string PictureUrl { get; init; } - } + public string PictureUrl { get; init; } } diff --git a/src/Web/WebMVC/ViewModels/Pagination/PaginationInfo.cs b/src/Web/WebMVC/ViewModels/Pagination/PaginationInfo.cs index a10280659..d06890673 100644 --- a/src/Web/WebMVC/ViewModels/Pagination/PaginationInfo.cs +++ b/src/Web/WebMVC/ViewModels/Pagination/PaginationInfo.cs @@ -1,12 +1,11 @@ -namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination +namespace Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination; + +public class PaginationInfo { - public class PaginationInfo - { - public int TotalItems { get; set; } - public int ItemsPerPage { get; set; } - public int ActualPage { get; set; } - public int TotalPages { get; set; } - public string Previous { get; set; } - public string Next { get; set; } - } + public int TotalItems { get; set; } + public int ItemsPerPage { get; set; } + public int ActualPage { get; set; } + public int TotalPages { get; set; } + public string Previous { get; set; } + public string Next { get; set; } } diff --git a/src/Web/WebMVC/Views/Order/Detail.cshtml b/src/Web/WebMVC/Views/Order/Detail.cshtml index 757700793..4b46f9921 100644 --- a/src/Web/WebMVC/Views/Order/Detail.cshtml +++ b/src/Web/WebMVC/Views/Order/Detail.cshtml @@ -40,7 +40,7 @@
-
Shiping address
+
Shipping address
diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj index ec922d36c..08b08a103 100644 --- a/src/Web/WebMVC/WebMVC.csproj +++ b/src/Web/WebMVC/WebMVC.csproj @@ -1,13 +1,12 @@ - net5.0 + net6.0 aspnet-Microsoft.eShopOnContainers-946ae052-8305-4a99-965b-ec8636ddbae3 ..\..\..\docker-compose.dcproj 3.0 false - true - preview + true @@ -25,16 +24,16 @@ - - - - - - + + + + + + - + diff --git a/src/Web/WebMVC/bundleconfig.json b/src/Web/WebMVC/bundleconfig.json index 5c5793da5..5b5707258 100644 --- a/src/Web/WebMVC/bundleconfig.json +++ b/src/Web/WebMVC/bundleconfig.json @@ -29,7 +29,7 @@ ], // Optionally specify minification options "minify": { - "enabled": true, + "enabled": false, "renameLocals": true }, // Optinally generate .map file diff --git a/src/Web/WebMVC/globalusings.cs b/src/Web/WebMVC/globalusings.cs new file mode 100644 index 000000000..3d8dbd8e0 --- /dev/null +++ b/src/Web/WebMVC/globalusings.cs @@ -0,0 +1,51 @@ +global using Devspaces.Support; +global using HealthChecks.UI.Client; +global using Microsoft.AspNetCore.Authentication.Cookies; +global using Microsoft.AspNetCore.Authentication.JwtBearer; +global using Microsoft.AspNetCore.Authentication.OpenIdConnect; +global using Microsoft.AspNetCore.Authentication; +global using Microsoft.AspNetCore.Authorization; +global using Microsoft.AspNetCore.Builder; +global using Microsoft.AspNetCore.DataProtection; +global using Microsoft.AspNetCore.Diagnostics.HealthChecks; +global using Microsoft.AspNetCore.Hosting; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Identity; +global using Microsoft.AspNetCore.Mvc.Rendering; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.AspNetCore; +global using Microsoft.eShopOnContainers.WebMVC.Services; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels.Annotations; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels.CartViewModels; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels.CatalogViewModels; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels.Pagination; +global using Microsoft.eShopOnContainers.WebMVC.ViewModels; +global using Microsoft.eShopOnContainers.WebMVC; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Diagnostics.HealthChecks; +global using Microsoft.Extensions.Hosting; +global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Options; +global using Microsoft.IdentityModel.Logging; +global using Serilog; +global using StackExchange.Redis; +global using System.Collections.Generic; +global using System.ComponentModel.DataAnnotations; +global using System.ComponentModel; +global using System.IdentityModel.Tokens.Jwt; +global using System.IO.Compression; +global using System.IO; +global using System.Linq; +global using System.Net.Http.Headers; +global using System.Net.Http; +global using System.Security.Claims; +global using System.Security.Principal; +global using System.Text.Json.Serialization; +global using System.Text.Json; +global using System.Text; +global using System.Threading.Tasks; +global using System.Threading; +global using System; +global using WebMVC.Infrastructure; +global using WebMVC.Services.ModelDTOs; \ No newline at end of file diff --git a/src/Web/WebSPA/.gitignore b/src/Web/WebSPA/.gitignore index a4cb1babf..393da938c 100644 --- a/src/Web/WebSPA/.gitignore +++ b/src/Web/WebSPA/.gitignore @@ -177,7 +177,8 @@ ClientBin/ *.publishsettings node_modules/ bower_components/ -wwwroot/ +wwwroot/* +!wwwroot/favicon.ico orleans.codegen.cs diff --git a/src/Web/WebSPA/AppSettings.cs b/src/Web/WebSPA/AppSettings.cs index 7c4b89b3c..941a5fdcd 100644 --- a/src/Web/WebSPA/AppSettings.cs +++ b/src/Web/WebSPA/AppSettings.cs @@ -1,14 +1,14 @@ -namespace eShopOnContainers.WebSPA +namespace eShopOnContainers.WebSPA; + +public class AppSettings { - public class AppSettings - { - public string IdentityUrl { get; set; } - public string BasketUrl { get; set; } + public string IdentityUrl { get; set; } + public string BasketUrl { get; set; } + public string MarketingUrl { get; set; } - public string PurchaseUrl { get; set; } - public string SignalrHubUrl { get; set; } + public string PurchaseUrl { get; set; } + public string SignalrHubUrl { get; set; } - public string ActivateCampaignDetailFunction { get; set; } - public bool UseCustomizationData { get; set; } - } + public string ActivateCampaignDetailFunction { get; set; } + public bool UseCustomizationData { get; set; } } diff --git a/src/Web/WebSPA/.npmignore b/src/Web/WebSPA/Client/.npmignore similarity index 100% rename from src/Web/WebSPA/.npmignore rename to src/Web/WebSPA/Client/.npmignore diff --git a/src/Web/WebSPA/.sass-lint.yml b/src/Web/WebSPA/Client/.sass-lint.yml similarity index 100% rename from src/Web/WebSPA/.sass-lint.yml rename to src/Web/WebSPA/Client/.sass-lint.yml diff --git a/src/Web/WebSPA/angular.json b/src/Web/WebSPA/Client/angular.json similarity index 76% rename from src/Web/WebSPA/angular.json rename to src/Web/WebSPA/Client/angular.json index dd21bfae8..7f95dc451 100644 --- a/src/Web/WebSPA/angular.json +++ b/src/Web/WebSPA/Client/angular.json @@ -5,23 +5,23 @@ "projects": { "WebSPA": { "root": "", - "sourceRoot": "Client", + "sourceRoot": "src", "projectType": "application", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { - "outputPath": "wwwroot", - "index": "Client/index.html", - "main": "Client/main.ts", - "tsConfig": "Client/tsconfig.app.json", - "polyfills": "Client/polyfills.ts", + "outputPath": "../wwwroot", + "index": "src/index.html", + "main": "src/main.ts", + "tsConfig": "src/tsconfig.app.json", + "polyfills": "src/polyfills.ts", "assets": [ - "Client/assets", - "Client/favicon.ico" + "src/assets", + "src/favicon.ico" ], "styles": [ - "Client/globals.scss" + "src/styles/globals.scss" ], "scripts": [] }, @@ -36,7 +36,6 @@ "optimization": true, "outputHashing": "all", "sourceMap": false, - "extractCss": true, "namedChunks": false, "aot": true, "extractLicenses": true, @@ -44,8 +43,8 @@ "buildOptimizer": true, "fileReplacements": [ { - "replace": "Client/environments/environment.ts", - "with": "Client/environments/environment.prod.ts" + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" } ] } @@ -71,17 +70,17 @@ "test": { "builder": "@angular-devkit/build-angular:karma", "options": { - "main": "Client/test.ts", + "main": "src/test.ts", "karmaConfig": "./karma.conf.js", - "polyfills": "Client/polyfills.ts", - "tsConfig": "Client/tsconfig.spec.json", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", "scripts": [], "styles": [ - "Client/globals.scss" + "src/styles/globals.scss" ], "assets": [ - "Client/assets", - "Client/favicon.ico" + "src/assets", + "src/favicon.ico" ] } }, @@ -89,8 +88,8 @@ "builder": "@angular-devkit/build-angular:tslint", "options": { "tsConfig": [ - "Client/tsconfig.app.json", - "Client/tsconfig.spec.json" + "src/tsconfig.app.json", + "src/tsconfig.spec.json" ], "exclude": [] } @@ -130,8 +129,5 @@ "@schematics/angular:directive": { "prefix": "app" } - }, - "cli": { - "analytics": false } } \ No newline at end of file diff --git a/src/Web/WebSPA/Client/assets/images/arrow-down.png b/src/Web/WebSPA/Client/assets/images/arrow-down.png deleted file mode 100644 index 1ebe2e929..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/arrow-down.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/brand.png b/src/Web/WebSPA/Client/assets/images/brand.png deleted file mode 100644 index c5257cbcf..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/brand.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/brand_dark.png b/src/Web/WebSPA/Client/assets/images/brand_dark.png deleted file mode 100644 index 23fbb4393..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/brand_dark.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/cart.png b/src/Web/WebSPA/Client/assets/images/cart.png deleted file mode 100644 index 158bcf797..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/cart.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/logout.png b/src/Web/WebSPA/Client/assets/images/logout.png deleted file mode 100644 index 9915b9862..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/logout.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/main_banner.png b/src/Web/WebSPA/Client/assets/images/main_banner.png deleted file mode 100644 index 19541e1ab..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/main_banner.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/main_banner_text.png b/src/Web/WebSPA/Client/assets/images/main_banner_text.png deleted file mode 100644 index 47315ef58..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/main_banner_text.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/main_footer_text.png b/src/Web/WebSPA/Client/assets/images/main_footer_text.png deleted file mode 100644 index 61cfa62ac..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/main_footer_text.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/assets/images/my_orders.png b/src/Web/WebSPA/Client/assets/images/my_orders.png deleted file mode 100644 index 145be925b..000000000 Binary files a/src/Web/WebSPA/Client/assets/images/my_orders.png and /dev/null differ diff --git a/src/Web/WebSPA/Client/favicon.ico b/src/Web/WebSPA/Client/favicon.ico deleted file mode 100644 index e499a7453..000000000 Binary files a/src/Web/WebSPA/Client/favicon.ico and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.eot b/src/Web/WebSPA/Client/fonts/Montserrat-Bold.eot deleted file mode 100644 index 1c57e5d95..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.eot and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.svg b/src/Web/WebSPA/Client/fonts/Montserrat-Bold.svg deleted file mode 100644 index b0cb0aeb6..000000000 --- a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.svg +++ /dev/null @@ -1,1933 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Sep 12 19:08:28 2016 - By ,,, -Copyright (c) 2011-2012, Julieta Ulanovsky (julieta.ulanovsky@gmail.com), with Reserved Font Names 'Montserrat' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.ttf b/src/Web/WebSPA/Client/fonts/Montserrat-Bold.ttf deleted file mode 100644 index ae33a4538..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.ttf and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.woff b/src/Web/WebSPA/Client/fonts/Montserrat-Bold.woff deleted file mode 100644 index 8ce1effc9..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.woff and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.woff2 b/src/Web/WebSPA/Client/fonts/Montserrat-Bold.woff2 deleted file mode 100644 index 16cf34a7c..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Bold.woff2 and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.eot b/src/Web/WebSPA/Client/fonts/Montserrat-Regular.eot deleted file mode 100644 index 64912c701..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.eot and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.svg b/src/Web/WebSPA/Client/fonts/Montserrat-Regular.svg deleted file mode 100644 index 8f2b72f12..000000000 --- a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.svg +++ /dev/null @@ -1,1743 +0,0 @@ - - - - -Created by FontForge 20120731 at Mon Sep 12 19:08:52 2016 - By ,,, -Copyright (c) 2011-2012, Julieta Ulanovsky (julieta.ulanovsky@gmail.com), with Reserved Font Names 'Montserrat' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.ttf b/src/Web/WebSPA/Client/fonts/Montserrat-Regular.ttf deleted file mode 100644 index 5b4b5afe6..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.ttf and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.woff b/src/Web/WebSPA/Client/fonts/Montserrat-Regular.woff deleted file mode 100644 index 930c783d1..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.woff and /dev/null differ diff --git a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.woff2 b/src/Web/WebSPA/Client/fonts/Montserrat-Regular.woff2 deleted file mode 100644 index 136ab68e9..000000000 Binary files a/src/Web/WebSPA/Client/fonts/Montserrat-Regular.woff2 and /dev/null differ diff --git a/src/Web/WebSPA/Client/globals.scss b/src/Web/WebSPA/Client/globals.scss deleted file mode 100644 index ae7613bbc..000000000 --- a/src/Web/WebSPA/Client/globals.scss +++ /dev/null @@ -1,80 +0,0 @@ -/* You can add global styles to this file, and also import other style files */ -@import "~bootstrap/scss/bootstrap"; -@import "~ngx-toastr/toastr-bs4-alert.scss"; - -@import './modules/variables'; - -$dist: './fonts/Montserrat-Regular'; - -@font-face { - font-family: Montserrat; - font-weight: 400; - src: url('./fonts/Montserrat-Regular.eot?') format('eot'), url('./fonts/Montserrat-Regular.woff') format('woff'), url('./fonts/Montserrat-Regular.ttf') format('truetype'), url('./fonts/Montserrat-Regular.svg#Montserrat') format('svg'); -} - -@font-face { - font-family: Montserrat; - font-weight: 700; - src: url('./fonts/Montserrat-Bold.eot?') format('eot'), url('./fonts/Montserrat-Bold.woff') format('woff'), url('./fonts/Montserrat-Bold.ttf') format('truetype'), url('./fonts/Montserrat-Bold.svg#Montserrat') format('svg'); -} - -html, -body { - font-family: Montserrat, sans-serif; - font-size: 16px; - font-weight: $font-weight-normal; - z-index: 10; -} - -*, -*::after, -*::before { - box-sizing: border-box; -} - -.preloading { - color: $color-brand; - display: block; - font-size: $font-size-xl; - left: 50%; - position: fixed; - top: 50%; - transform: translate(-50%, -50%); -} - -select::-ms-expand { - display: none; -} - -@media screen and (min-width: 992px) { - .form-input { - max-width: 360px; - width: 360px; - } -} - -.form-input { - border-radius: 0; - height: 45px; - padding: 10px; -} - -.form-input-small { - max-width: 100px !important; -} - -.form-input-medium { - width: 150px !important; -} - -.alert { - padding-left: 0; -} - -.alert-danger { - background-color: transparent; - border: 0; - color: #FB0D0D; - font-size: 12px; -} - diff --git a/src/Web/WebSPA/Client/modules/_variables.scss b/src/Web/WebSPA/Client/modules/_variables.scss deleted file mode 100644 index cae5cc3b7..000000000 --- a/src/Web/WebSPA/Client/modules/_variables.scss +++ /dev/null @@ -1,58 +0,0 @@ -// Colors -$color-brand: #00A69C; -$color-brand-dark: darken($color-brand, 10%); -$color-brand-darker: darken($color-brand, 20%); -$color-brand-bright: lighten($color-brand, 10%); -$color-brand-brighter: lighten($color-brand, 20%); - -$color-secondary: #83D01B; -$color-secondary-dark: darken($color-secondary, 5%); -$color-secondary-darker: darken($color-secondary, 20%); -$color-secondary-bright: lighten($color-secondary, 10%); -$color-secondary-brighter: lighten($color-secondary, 20%); - -$color-background-dark: #333333; -$color-background-darker: #000000; -$color-background-bright: #EEEEFF; -$color-background-brighter: #FFFFFF; - -$color-foreground-dark: #333333; -$color-foreground-darker: #000000; -$color-foreground-bright: #EEEEEE; -$color-foreground-brighter: #FFFFFF; - -// Animations -$animation-speed-default: .35s; -$animation-speed-slow: .5s; -$animation-speed-fast: .15s; - -// Fonts -$font-weight-light: 200; -$font-weight-semilight: 300; -$font-weight-normal: 400; -$font-weight-semibold: 600; -$font-weight-bold: 700; - -$font-size-xs: .65rem; // 10.4px -$font-size-s: .85rem; // 13.6px -$font-size-m: 1rem; // 16px -$font-size-l: 1.25rem; // 20px -$font-size-xl: 1.5rem; // 24px - -// Medias -$media-screen-xxs: 360px; -$media-screen-xs: 640px; -$media-screen-s: 768px; -$media-screen-m: 1024px; -$media-screen-l: 1280px; -$media-screen-xl: 1440px; -$media-screen-xxl: 1680px; -$media-screen-xxxl: 1920px; - -// Borders -$border-light: 1px; - -// Images -$image_path: '/assets/images/'; -$image-main_banner: '#{$image_path}main_banner.png'; -$image-arrow_down: '#{$image_path}arrow-down.png'; \ No newline at end of file diff --git a/src/Web/WebSPA/Client/modules/app.component.html b/src/Web/WebSPA/Client/modules/app.component.html deleted file mode 100644 index 2c33b2e5d..000000000 --- a/src/Web/WebSPA/Client/modules/app.component.html +++ /dev/null @@ -1,40 +0,0 @@ -
-
-
-
- - - -
- -
- -
- -
- -
- -
-
-
- - - - -
-
-
- -
- -
- -
- -
- -
-
-
- diff --git a/src/Web/WebSPA/Client/modules/app.component.scss b/src/Web/WebSPA/Client/modules/app.component.scss deleted file mode 100644 index 04d595948..000000000 --- a/src/Web/WebSPA/Client/modules/app.component.scss +++ /dev/null @@ -1,27 +0,0 @@ -@import './variables'; - -.esh-app { - &-footer { - $margin: 2.5rem; - $padding: 2.5rem; - - background-color: $color-background-darker; - border-top: $border-light solid $color-foreground-bright; - margin-top: $margin; - padding-bottom: $padding; - padding-top: $padding; - width: 100%; - bottom: 0; - - $height: 50px; - - &-brand { - height: $height; - width: 230px; - } - } - - &-header { - margin: 15px; - } -} diff --git a/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.scss b/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.scss deleted file mode 100644 index d7c91e7a8..000000000 --- a/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.scss +++ /dev/null @@ -1,41 +0,0 @@ -@import '../../variables'; - -.esh-basketstatus { - cursor: pointer; - display: inline-block; - float: right; - position: relative; - transition: all $animation-speed-default; - - &.is-disabled { - opacity: .5; - pointer-events: none; - } - - &-image { - height: 36px; - margin-top: .5rem; - } - - &-badge { - $size: 1.5rem; - background-color: $color-secondary; - border-radius: 50%; - color: $color-foreground-brighter; - display: block; - height: $size; - left: 50%; - position: absolute; - text-align: center; - top: 0; - transform: translateX(-38%); - transition: all $animation-speed-default; - width: $size; - } - - &:hover &-badge { - background-color: transparent; - color: $color-secondary-dark; - transition: all $animation-speed-default; - } -} diff --git a/src/Web/WebSPA/Client/modules/basket/basket.component.html b/src/Web/WebSPA/Client/modules/basket/basket.component.html deleted file mode 100644 index 72edb9ace..000000000 --- a/src/Web/WebSPA/Client/modules/basket/basket.component.html +++ /dev/null @@ -1,65 +0,0 @@ -
- Back to catalog - -
-
-
- -
-
- -
-
Product
-
-
Price
-
Quantity
-
Cost
-
- -
-
- -
- -
-
{{item.productName}}
-
$ {{item.unitPrice | number:'.2-2'}}
-
- -
-
$ {{(item.unitPrice * item.quantity) | number:'.2-2'}}
-
-
-
- -
-
-
- -
-
-
-
Total
-
- -
-
-
$ {{totalPrice | number:'.2-2'}}
-
- -
-
-
- -
-
-
[ Checkout ]
-
-
-
-
diff --git a/src/Web/WebSPA/Client/modules/basket/basket.component.scss b/src/Web/WebSPA/Client/modules/basket/basket.component.scss deleted file mode 100644 index c0e6c61fd..000000000 --- a/src/Web/WebSPA/Client/modules/basket/basket.component.scss +++ /dev/null @@ -1,89 +0,0 @@ -@import '../variables'; - -@mixin margin-left($distance) { - margin-left: $distance; -} - -.esh-basket { - min-height: 80vh; - - &-titles { - padding-bottom: 1rem; - padding-top: 2rem; - - &--clean { - padding-bottom: 0; - padding-top: 0; - } - } - - &-title { - text-transform: uppercase; - } - - &-items { - &--border { - border-bottom: $border-light solid $color-foreground-bright; - padding: .5rem 0; - - &:last-of-type { - border-color: transparent; - } - } - - &-margin-left1 { - @include margin-left(1px); - } - } - - $item-height: 8rem; - - &-item { - font-size: $font-size-m; - font-weight: $font-weight-semilight; - - &--middle { - line-height: $item-height; - - @media screen and (max-width: $media-screen-m) { - line-height: $font-size-m; - } - } - - &--mark { - color: $color-brand; - } - } - - &-image { - height: $item-height; - } - - &-input { - line-height: 1rem; - width: 100%; - } - - &-checkout { - background-color: $color-secondary; - border: 0; - border-radius: 0; - color: $color-foreground-brighter; - display: inline-block; - font-size: 1rem; - font-weight: $font-weight-normal; - margin-top: 1rem; - padding: 1rem 1.5rem; - text-align: center; - text-transform: uppercase; - transition: all $animation-speed-default; - - &:hover { - background-color: $color-secondary-darker; - transition: all $animation-speed-default; - } - } -} - - - diff --git a/src/Web/WebSPA/Client/modules/catalog/catalog.component.html b/src/Web/WebSPA/Client/modules/catalog/catalog.component.html deleted file mode 100644 index d03b8433b..000000000 --- a/src/Web/WebSPA/Client/modules/catalog/catalog.component.html +++ /dev/null @@ -1,54 +0,0 @@ -
-
- -
-
- -
-
- - - - -
-
- -
-
- - -
-
- - - - -
- {{item.name}} -
-
- {{item.price | number:'.2-2'}} -
-
-
- - -
-
- THERE ARE NO RESULTS THAT MATCH YOUR SEARCH -
-
- diff --git a/src/Web/WebSPA/Client/modules/catalog/catalog.component.scss b/src/Web/WebSPA/Client/modules/catalog/catalog.component.scss deleted file mode 100644 index 304334013..000000000 --- a/src/Web/WebSPA/Client/modules/catalog/catalog.component.scss +++ /dev/null @@ -1,158 +0,0 @@ -@import '../variables'; - -.esh-catalog { - $banner-height: 260px; - - &-hero { - background-image: url($image-main_banner); - background-size: cover; - height: $banner-height; - width: 100%; - } - - &-title { - position: relative; - top: $banner-height / 3.5; - } - - $filter-height: 65px; - - &-filters { - background-color: $color-brand; - height: $filter-height; - } - - $filter-padding: .5rem; - - &-filter { - -webkit-appearance: none; - background-color: transparent; - border-color: $color-brand-bright; - color: $color-foreground-brighter; - cursor: pointer; - margin-right: 1rem; - margin-top: .5rem; - min-width: 140px; - outline-color: $color-secondary; - padding-bottom: 0; - padding-left: $filter-padding; - padding-right: $filter-padding; - padding-top: $filter-padding * 3; - - option { - background-color: $color-brand; - } - } - - &-label { - display: inline-block; - position: relative; - z-index: 0; - - &::before { - color: rgba($color-foreground-brighter, .5); - content: attr(data-title); - font-size: $font-size-xs; - margin-left: $filter-padding; - margin-top: $font-size-xs; - position: absolute; - text-transform: uppercase; - z-index: 1; - } - - &::after { - background-image: url($image-arrow_down); - content: ''; - height: 7px; //png height - position: absolute; - right: $filter-padding * 3; - top: $filter-padding * 5; - width: 10px; //png width - z-index: 1; - } - } - - &-send { - background-color: $color-secondary; - color: $color-foreground-brighter; - cursor: pointer; - font-size: $font-size-m; - margin-top: -$filter-padding * 3; - padding: $filter-padding; - transition: all $animation-speed-default; - - &:hover { - background-color: $color-secondary-darker; - transition: all $animation-speed-default; - } - } - - &-items { - margin-top: 1rem; - } - - &-item { - margin-bottom: 1.5rem; - text-align: center; - width: 33%; - display: inline-block; - float: none !important; - - @media screen and (max-width: $media-screen-m) { - width: 50%; - } - - @media screen and (max-width: $media-screen-s) { - width: 100%; - } - } - - &-thumbnail { - max-width: 370px; - width: 100%; - } - - &-button { - background-color: $color-secondary; - border: 0; - color: $color-foreground-brighter; - cursor: pointer; - font-size: $font-size-m; - height: 3rem; - margin-top: 1rem; - transition: all $animation-speed-default; - width: 80%; - - &.is-disabled { - opacity: .5; - pointer-events: none; - } - - &:hover { - background-color: $color-secondary-darker; - transition: all $animation-speed-default; - } - } - - &-name { - font-size: $font-size-m; - font-weight: $font-weight-semilight; - margin-top: .5rem; - text-align: center; - text-transform: uppercase; - } - - &-price { - font-size: 28px; - font-weight: 900; - text-align: center; - - &::before { - content: '$'; - } - } - - &-alert { - margin-top: 10px; - } -} diff --git a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html b/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html deleted file mode 100644 index c9ff9488c..000000000 --- a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html +++ /dev/null @@ -1,78 +0,0 @@ -
- Back to list - -
-
-
-
Order number
-
Date
-
Total
-
Status
-
- -
-
{{order.ordernumber}}
-
{{order.date | date:'short'}}
-
$ {{order.total}}
-
{{order.status}}
-
-
- -
-
-
Description
-
- -
-
{{order.description}}
-
-
- -
-
-
Shiping address
-
- -
-
{{order.street}}
-
- -
-
{{order.city}}
-
- -
-
{{order.country}}
-
-
- -
-
-
Order details
-
- -
-
- -
-
{{item.productname}}
-
$ {{item.unitprice | number:'.2-2'}}
-
{{item.units}}
-
$ {{(item.units * item.unitprice) | number:'.2-2'}}
-
-
- -
-
-
-
Total
-
- -
-
-
$ {{order.total | number:'.2-2'}}
-
-
-
-
diff --git a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.scss b/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.scss deleted file mode 100644 index d5245a88a..000000000 --- a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.scss +++ /dev/null @@ -1,56 +0,0 @@ -@import '../../variables'; - -.esh-orders_detail { - min-height: 80vh; - - &-section { - padding: 1rem 0; - - &--right { - text-align: right; - } - } - - &-titles { - padding-bottom: 1rem; - padding-top: 2rem; - } - - &-title { - text-transform: uppercase; - } - - &-items { - &--border { - border-bottom: $border-light solid $color-foreground-bright; - padding: .5rem 0; - - &:last-of-type { - border-color: transparent; - } - } - } - - $item-height: 8rem; - - &-item { - font-size: $font-size-m; - font-weight: $font-weight-semilight; - - &--middle { - line-height: $item-height; - - @media screen and (max-width: $media-screen-s) { - line-height: $font-size-m; - } - } - - &--mark { - color: $color-secondary; - } - } - - &-image { - height: $item-height; - } -} diff --git a/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.html b/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.html deleted file mode 100644 index 2fed9e9a5..000000000 --- a/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.html +++ /dev/null @@ -1,116 +0,0 @@ - - -
- -
-
-

Shipping Address

-
-
-
- - -
Required field.
-
-
-
-
- - -
Required field.
-
-
-
-
- - -
Required field.
-
-
-
-
- - -
Required field.
-
-
-
-
-
-

Payment method

-
-
-
- - -
Required field.
-
-
-
-
- - -
Required field.
-
-
-
-
- - -
Required field.
-
-
-
-
- - -
Required field.
-
-
-
-
-
-
-
Order details
-
- -
-
- -
-
{{item.productname}}
-
$ {{item.unitprice | number:'.2-2'}}
-
{{item.units}}
-
$ {{(item.units * item.unitprice) | number:'.2-2'}}
-
-
- -
-
-
-
Total
-
- -
-
-
$ {{order.total | number:'.2-2'}}
-
-
-
-
-
-
-
- -
-
-
-
-
\ No newline at end of file diff --git a/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.scss b/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.scss deleted file mode 100644 index bae6fb6ee..000000000 --- a/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.scss +++ /dev/null @@ -1,101 +0,0 @@ -@import '../../variables'; - -.esh-orders_new { - min-height: 80vh; - - $header-height: 4rem; - - &-header { - background-color: #00A69C; - height: $header-height; - } - - &-back { - color: rgba($color-foreground-brighter, .4); - line-height: $header-height; - text-decoration: none; - text-transform: uppercase; - transition: color $animation-speed-default; - - &:hover { - color: $color-foreground-brighter; - transition: color $animation-speed-default; - } - } - - &-section { - padding: 1rem 0; - - &--right { - text-align: right; - } - } - - &-placeOrder { - background-color: $color-secondary; - border: 0; - border-radius: 0; - color: $color-foreground-brighter; - display: inline-block; - font-size: 1rem; - font-weight: $font-weight-normal; - margin-top: 1rem; - padding: 1rem 1.5rem; - text-align: center; - text-transform: uppercase; - transition: all $animation-speed-default; - - &:hover { - background-color: $color-secondary-darker; - transition: all $animation-speed-default; - } - } - - &-titles { - padding-bottom: 1rem; - padding-top: 2rem; - } - - &-title { - font-size: $font-size-l; - text-transform: uppercase; - } - - &-items { - &--border { - border-bottom: $border-light solid $color-foreground-bright; - padding: .5rem 0; - - &:last-of-type { - border-color: transparent; - } - } - } - - $item-height: 8rem; - - &-item { - font-size: $font-size-m; - font-weight: $font-weight-semilight; - - &--middle { - line-height: $item-height; - - @media screen and (max-width: $media-screen-s) { - line-height: $font-size-m; - } - } - - &--mark { - color: $color-secondary; - } - } - - &-image { - height: $item-height; - } - - &-alert { - margin-top: 10px; - } -} diff --git a/src/Web/WebSPA/Client/modules/orders/orders.component.html b/src/Web/WebSPA/Client/modules/orders/orders.component.html deleted file mode 100644 index cd98b1a1a..000000000 --- a/src/Web/WebSPA/Client/modules/orders/orders.component.html +++ /dev/null @@ -1,27 +0,0 @@ -
- Back to catalog - -
- -
-
Order number
-
Date
-
Total
-
Status
-
-
- -
-
{{order.ordernumber}}
-
{{order.date | date:'short'}}
-
$ {{order.total}}
-
{{order.status}}
-
- Detail -
-
-
-
diff --git a/src/Web/WebSPA/Client/modules/orders/orders.component.scss b/src/Web/WebSPA/Client/modules/orders/orders.component.scss deleted file mode 100644 index c7a6a7664..000000000 --- a/src/Web/WebSPA/Client/modules/orders/orders.component.scss +++ /dev/null @@ -1,85 +0,0 @@ -@import '../variables'; - -.esh-orders { - min-height: 80vh; - overflow-x: hidden; - - $header-height: 4rem; - - &-header { - background-color: #00A69C; - height: $header-height; - } - - &-back { - color: rgba($color-foreground-brighter, .4); - line-height: $header-height; - text-decoration: none; - text-transform: uppercase; - transition: color $animation-speed-default; - - &:hover { - color: $color-foreground-brighter; - transition: color $animation-speed-default; - } - } - - &-titles { - padding-bottom: 1rem; - padding-top: 2rem; - } - - &-title { - text-transform: uppercase; - } - - &-items { - $height: 2rem; - height: $height; - line-height: $height; - position: relative; - - &:nth-of-type(2n + 1) { - &:before { - background-color: $color-background-bright; - content: ''; - height: 100%; - left: 0; - margin-left: -100vw; - position: absolute; - top: 0; - width: 200vw; - z-index: -1; - } - } - } - - &-item { - font-weight: $font-weight-semilight; - - &--hover { - opacity: 0; - pointer-events: none; - } - } - - &-items:hover &-item--hover { - opacity: 1; - pointer-events: all; - } - - &-link { - color: $color-secondary; - text-decoration: none; - transition: color $animation-speed-default; - - &:hover { - color: $color-secondary-dark; - transition: color $animation-speed-default; - } - } - - &-alert { - margin-top: 10px; - } -} diff --git a/src/Web/WebSPA/Client/modules/shared/components/identity/identity.html b/src/Web/WebSPA/Client/modules/shared/components/identity/identity.html deleted file mode 100644 index 9dce33adc..000000000 --- a/src/Web/WebSPA/Client/modules/shared/components/identity/identity.html +++ /dev/null @@ -1,35 +0,0 @@ -
-
-
- -
Login
-
-
- -
- -
{{userName}}
- -
- -
- -
- -
My orders
- -
- -
- -
Log Out
- -
-
-
diff --git a/src/Web/WebSPA/Client/modules/shared/components/identity/identity.scss b/src/Web/WebSPA/Client/modules/shared/components/identity/identity.scss deleted file mode 100644 index 0939ee9c6..000000000 --- a/src/Web/WebSPA/Client/modules/shared/components/identity/identity.scss +++ /dev/null @@ -1,57 +0,0 @@ -@import '../../../variables'; - -.esh-identity { - line-height: 2.1rem; - position: relative; - text-align: right; - - &-section { - display: inline-block; - width: 100%; - } - - &-name { - display: inline-block; - margin-right: 10px; - - &--upper { - text-transform: uppercase; - } - - @media screen and (max-width: $media-screen-s) { - font-size: $font-size-s; - } - } - - &-image { - display: inline-block; - } - - &-drop { - background: $color-background-brighter; - height: 0; - min-width: 14rem; - overflow: hidden; - padding: .3rem; - position: absolute; - right: 0; - top: 2.8rem; - transition: height $animation-speed-default; - } - - &:hover &-drop { - border: $border-light solid $color-foreground-bright; - height: 7rem; - transition: height $animation-speed-default; - } - - &-item { - cursor: pointer; - transition: color $animation-speed-default; - - &:hover { - color: $color-secondary-dark; - transition: color $animation-speed-default; - } - } -} diff --git a/src/Web/WebSPA/Client/package-lock.json b/src/Web/WebSPA/Client/package-lock.json new file mode 100644 index 000000000..076f5a0ef --- /dev/null +++ b/src/Web/WebSPA/Client/package-lock.json @@ -0,0 +1,39201 @@ +{ + "name": "eshopaspnetnetcoredockerspa", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "eshopaspnetnetcoredockerspa", + "version": "0.0.0", + "dependencies": { + "@angular-devkit/schematics": "^11.0.4", + "@angular/animations": "11.2.14", + "@angular/common": "11.2.14", + "@angular/compiler": "11.2.14", + "@angular/core": "11.2.14", + "@angular/forms": "11.2.14", + "@angular/platform-browser": "11.2.14", + "@angular/platform-browser-dynamic": "11.2.14", + "@angular/platform-server": "11.2.14", + "@angular/router": "11.2.14", + "@microsoft/signalr": "3.0.1", + "@ng-bootstrap/ng-bootstrap": "^8.0.0", + "@popperjs/core": "2.0.0", + "acorn": "^6.4.1", + "acorn-dynamic-import": "4.0.0", + "bootstrap": "4.4.1", + "core-js": "^3.14.0", + "file-loader": "2.0.0", + "font-awesome": "4.7.0", + "is-svg": ">=4.2.2", + "isomorphic-fetch": "3.0.0", + "jquery": "3.5.0", + "ngx-toastr": "^13.2.0", + "normalize.css": "8.0.0", + "popper.js": "1.16.1", + "rxjs": "^6.5.2", + "rxjs-compat": "^6.5.2", + "ssri": ">=8.0.1", + "tslib": "^2.0.0", + "typedoc": "0.22.11", + "webpack-dev-server": "4.7.4", + "zone.js": "~0.10.2" + }, + "devDependencies": { + "@angular-devkit/build-angular": "~0.1102.14", + "@angular/cli": "11.2.14", + "@angular/compiler-cli": "11.2.14", + "@angular/language-service": "11.2.14", + "@types/core-js": "2.5.0", + "@types/hammerjs": "2.0.35", + "@types/jasmine": "~3.6.0", + "@types/node": "^12.11.1", + "@types/protractor": "4.0.0", + "@types/selenium-webdriver": "3.0.10", + "codelyzer": "^6.0.0", + "eslint": "8.10.0", + "handlebars": "^4.7.7", + "jasmine-core": "~3.6.0", + "jasmine-spec-reporter": "~5.0.0", + "karma": "~6.3.16", + "karma-chrome-launcher": "~3.1.0", + "karma-cli": "^2.0.0", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "lodash": "^4.17.21", + "merge": "2.1.1", + "npm-watch": "0.5.0", + "protractor": "~7.0.0", + "rxjs-tslint": "^0.1.8", + "sass-lint": "^1.13.1", + "ts-helpers": "1.1.2", + "ts-node": "~7.0.1", + "tslint": "~6.1.0", + "typedoc": "0.22.11", + "typescript": "4.0.8", + "url-loader": "1.1.1", + "webpack": "^4.42.1" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1102.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1102.14.tgz", + "integrity": "sha512-965TVXuBtRb8RySgxRxUEO+YTd7mT0xiqVHSe+MHvMtUCmEE9vwRofFZl6axkK5ri4fiomiMnOVE19aw4spgNQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.2.14", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1102.19.tgz", + "integrity": "sha512-frI8UyujPB5WV7l9uecH8Ev73TWTV7xEHrwYIKryD/mVmqeg64ILi4/ATPHm1qGFjAH27WWHtzL2vnik5wBlNg==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1102.19", + "@angular-devkit/build-optimizer": "0.1102.19", + "@angular-devkit/build-webpack": "0.1102.19", + "@angular-devkit/core": "11.2.19", + "@babel/core": "7.12.10", + "@babel/generator": "7.12.11", + "@babel/plugin-transform-async-to-generator": "7.12.1", + "@babel/plugin-transform-runtime": "7.12.10", + "@babel/preset-env": "7.12.11", + "@babel/runtime": "7.12.5", + "@babel/template": "7.12.7", + "@discoveryjs/json-ext": "0.5.2", + "@jsdevtools/coverage-istanbul-loader": "3.0.5", + "@ngtools/webpack": "11.2.19", + "ansi-colors": "4.1.1", + "autoprefixer": "10.2.4", + "babel-loader": "8.2.2", + "browserslist": "^4.9.1", + "cacache": "15.0.5", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.2", + "copy-webpack-plugin": "6.3.2", + "core-js": "3.8.3", + "critters": "0.0.12", + "css-loader": "5.0.1", + "cssnano": "5.0.2", + "file-loader": "6.2.0", + "find-cache-dir": "3.3.1", + "glob": "7.1.6", + "https-proxy-agent": "5.0.0", + "inquirer": "7.3.3", + "jest-worker": "26.6.2", + "karma-source-map-support": "1.4.0", + "less": "4.1.1", + "less-loader": "7.3.0", + "license-webpack-plugin": "2.3.11", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "1.3.5", + "minimatch": "3.0.4", + "open": "7.4.0", + "ora": "5.3.0", + "parse5-html-rewriting-stream": "6.0.1", + "pnp-webpack-plugin": "1.6.4", + "postcss": "8.2.15", + "postcss-import": "14.0.0", + "postcss-loader": "4.2.0", + "raw-loader": "4.0.2", + "regenerator-runtime": "0.13.7", + "resolve-url-loader": "4.0.0", + "rimraf": "3.0.2", + "rollup": "2.38.4", + "rxjs": "6.6.3", + "sass": "1.32.6", + "sass-loader": "10.1.1", + "semver": "7.3.4", + "source-map": "0.7.3", + "source-map-loader": "1.1.3", + "source-map-support": "0.5.19", + "speed-measure-webpack-plugin": "1.4.2", + "style-loader": "2.0.0", + "stylus": "0.54.8", + "stylus-loader": "4.3.3", + "terser": "5.5.1", + "terser-webpack-plugin": "4.2.3", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "webpack": "4.44.2", + "webpack-dev-middleware": "3.7.2", + "webpack-dev-server": "3.11.3", + "webpack-merge": "5.7.3", + "webpack-sources": "2.2.0", + "webpack-subresource-integrity": "1.5.2", + "worker-plugin": "5.0.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^11.0.0 || ^11.2.0-next", + "@angular/localize": "^11.0.0 || ^11.2.0-next", + "@angular/service-worker": "^11.0.0 || ^11.2.0-next", + "karma": "^5.2.0 || ^6.0.0", + "ng-packagr": "^11.0.0 || ^11.2.0-next", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0", + "tslint": "^6.1.0", + "typescript": "~4.0.0 || ~4.1.0" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + }, + "tslint": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/architect": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1102.19.tgz", + "integrity": "sha512-5Opv6H+XyCkuQvQ1jsxw416YqMDPX3dVonMarFGBPLBe8YEXLRTJ60dvmuLsLpWk6ccTd3XiNT7WEJy4ctDc2Q==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.2.19", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/build-webpack": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1102.19.tgz", + "integrity": "sha512-IhN/eeaA2bA1daLTU7YDztxvaS9Hj2J2t889fBYn5xNnM3Z2QqwyncOoj0F0Cumx6tuFtwRSvaKm7+xbbCoJQA==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1102.19", + "@angular-devkit/core": "11.2.19", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^4.6.0", + "webpack-dev-server": "^3.1.4" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { + "version": "11.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.19.tgz", + "integrity": "sha512-kvS0QXDYDatLyf0NYv2sahPYD7kya4g5GpQAV1ddjjLmEVeZssHt+Xfk2tzrkzYzqRMiyspx3HPPrrOnMUAFhQ==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@angular-devkit/build-angular/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" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/core-js": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", + "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/del/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/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==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "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/@angular-devkit/build-angular/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "dependencies": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/@angular-devkit/build-angular/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==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/make-dir/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/@angular-devkit/build-angular/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==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/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==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "dependencies": { + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "dependencies": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/terser-webpack-plugin/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==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/terser-webpack-plugin/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/@angular-devkit/build-angular/node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/terser-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 6.11.5" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server/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/@angular-devkit/build-angular/node_modules/webpack/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/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/@angular-devkit/build-angular/node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@angular-devkit/build-optimizer": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1102.19.tgz", + "integrity": "sha512-3665mNFwOCqD2HR6Kjrwqh+Jh72h3F7AB88p/oWBvH0GolFCz8JnbwUZJkzTtOsKUw5ZC1Z6b/nbUkCJemxFug==", + "dev": true, + "dependencies": { + "loader-utils": "2.0.0", + "source-map": "0.7.3", + "tslib": "2.1.0", + "typescript": "4.1.5", + "webpack-sources": "2.2.0" + }, + "bin": { + "build-optimizer": "src/build-optimizer/cli.js" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/typescript": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", + "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.14.tgz", + "integrity": "sha512-Ad1fHqLxDwhkQgLPqq9i+G65NSOoIHXQx7ILcSPACKurV3XLS1RO9BgP/BDaqHAG+WslUAPbMStaTzzPm+9dNw==", + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/core/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@angular-devkit/core/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/@angular-devkit/schematics": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-11.2.14.tgz", + "integrity": "sha512-Ol6+0qdGKzuVJm5gCtQr47X0OCihTfAxI4h047cHYhPFIGGPSvkG/QeJMZugflgoobi2k/xcYokOu/VAkRtWbQ==", + "dependencies": { + "@angular-devkit/core": "11.2.14", + "ora": "5.3.0", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/schematics/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/@angular/animations": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-11.2.14.tgz", + "integrity": "sha512-Heq/nNrCmb3jbkusu+BQszOecfFI/31Oxxj+CDQkqqYpBcswk6bOJLoEE472o+vmgxaXbgeflU9qbIiCQhpMFA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "11.2.14" + } + }, + "node_modules/@angular/cli": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-11.2.14.tgz", + "integrity": "sha512-8Ud7vcUK7CKjzT2Ks1glLhleAPIC5ChcrA15XtOb7k+/uMHBkMscP/UKymbVQiBjCJlglbzJoyj8cpVYTZY5KA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@angular-devkit/architect": "0.1102.14", + "@angular-devkit/core": "11.2.14", + "@angular-devkit/schematics": "11.2.14", + "@schematics/angular": "11.2.14", + "@schematics/update": "0.1102.14", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "4.3.1", + "ini": "2.0.0", + "inquirer": "7.3.3", + "jsonc-parser": "3.0.0", + "npm-package-arg": "8.1.0", + "npm-pick-manifest": "6.1.0", + "open": "7.4.0", + "ora": "5.3.0", + "pacote": "11.2.4", + "resolve": "1.19.0", + "rimraf": "3.0.2", + "semver": "7.3.4", + "symbol-observable": "3.0.0", + "universal-analytics": "0.4.23", + "uuid": "8.3.2" + }, + "bin": { + "ng": "bin/ng" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/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" + } + }, + "node_modules/@angular/cli/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular/cli/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular/cli/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==", + "dev": true + }, + "node_modules/@angular/cli/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@angular/cli/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@angular/cli/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@angular/cli/node_modules/symbol-observable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-3.0.0.tgz", + "integrity": "sha512-6tDOXSHiVjuCaasQSWTmHUWn4PuG7qa3+1WT031yTc/swT7+rLiw3GOrFxaH1E3lLP09dH3bVuVDf2gK5rxG3Q==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/@angular/cli/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==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@angular/cli/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@angular/common": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-11.2.14.tgz", + "integrity": "sha512-ZSLV/3j7eCTyLf/8g4yBFLWySjiLz3vLJAGWscYoUpnJWMnug1VRu6zoF/COxCbtORgE+Wz6K0uhfS6MziBGVw==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "11.2.14", + "rxjs": "^6.5.3" + } + }, + "node_modules/@angular/compiler": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-11.2.14.tgz", + "integrity": "sha512-XBOK3HgA+/y6Cz7kOX4zcJYmgJ264XnfcbXUMU2cD7Ac+mbNhLPKohWrEiSWalfcjnpf5gRfufQrQP7lpAGu0A==", + "dependencies": { + "tslib": "^2.0.0" + } + }, + "node_modules/@angular/compiler-cli": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-11.2.14.tgz", + "integrity": "sha512-A7ltnCp03/EVqK/Q3tVUDsokgz5GHW3dSPGl0Csk7Ys5uBB9ibHTmVt4eiXA4jt0+6Bk+mKxwe5BEDqLvwYFAg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "fs-extra": "4.0.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^6.3.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "ivy-ngcc": "ngcc/main-ivy-ngcc.js", + "ng-xi18n": "src/extract_i18n.js", + "ngc": "src/main.js", + "ngcc": "ngcc/main-ngcc.js" + }, + "engines": { + "node": ">=10.0" + }, + "peerDependencies": { + "@angular/compiler": "11.2.14", + "typescript": ">=4.0 <4.2" + } + }, + "node_modules/@angular/compiler-cli/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@angular/compiler-cli/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" + } + }, + "node_modules/@angular/compiler-cli/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/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/@angular/compiler-cli/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/@angular/compiler-cli/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==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/node_modules/fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/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/@angular/compiler-cli/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==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@angular/compiler-cli/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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular/compiler-cli/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==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/@angular/compiler-cli/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/@angular/compiler-cli/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/@angular/core": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-11.2.14.tgz", + "integrity": "sha512-vpR4XqBGitk1Faph37CSpemwIYTmJ3pdIVNoHKP6jLonpWu+0azkchf0f7oD8/2ivj2F81opcIw0tcsy/D/5Vg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3", + "zone.js": "^0.10.2 || ^0.11.3" + } + }, + "node_modules/@angular/forms": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-11.2.14.tgz", + "integrity": "sha512-4LWqY6KEIk1AZQFnk+4PJSOCamlD4tumuVN06gO4D0dZo9Cx+GcvW6pM6N0CPubRvPs3sScCnu20WT11HNWC1w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "11.2.14", + "@angular/core": "11.2.14", + "@angular/platform-browser": "11.2.14", + "rxjs": "^6.5.3" + } + }, + "node_modules/@angular/language-service": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-11.2.14.tgz", + "integrity": "sha512-3+0F0X4r1WeNOV6VmaMzYnJENPVmLX2/MX3/lugwZPNYKVXl/oGyh/4PB8ktntIj0tnxQuErzqRSeucNStNGRw==", + "dev": true + }, + "node_modules/@angular/platform-browser": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-11.2.14.tgz", + "integrity": "sha512-fb7b7ss/gRoP8wLAN17W62leMgjynuyjEPU2eUoAAazsG9f2cgM+z3rK29GYncDVyYQxZUZYnjSqvL6GSXx86A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/animations": "11.2.14", + "@angular/common": "11.2.14", + "@angular/core": "11.2.14" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.2.14.tgz", + "integrity": "sha512-TWTPdFs6iBBcp+/YMsgCRQwdHpWGq8KjeJDJ2tfatGgBD3Gqt2YaHOMST1zPW6RkrmupytTejuVqXzeaKWFxuw==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "11.2.14", + "@angular/compiler": "11.2.14", + "@angular/core": "11.2.14", + "@angular/platform-browser": "11.2.14" + } + }, + "node_modules/@angular/platform-server": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-11.2.14.tgz", + "integrity": "sha512-VSJ4FSyMPVCE3EGfD4hIK1fZu+KFYi04uL4Co8vchzBQFpXPFABpCS/lGd7rOyvLnKRmUvl4NGS72gQdS00IUw==", + "dependencies": { + "domino": "^2.1.2", + "tslib": "^2.0.0", + "xhr2": "^0.2.0" + }, + "engines": { + "node": ">=8.0" + }, + "peerDependencies": { + "@angular/animations": "11.2.14", + "@angular/common": "11.2.14", + "@angular/compiler": "11.2.14", + "@angular/core": "11.2.14", + "@angular/platform-browser": "11.2.14", + "@angular/platform-browser-dynamic": "11.2.14" + } + }, + "node_modules/@angular/router": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-11.2.14.tgz", + "integrity": "sha512-3aYBmj+zrEL9yf/ntIQxHIYaWShZOBKP3U07X2mX+TPMpGlvHDnR7L6bWhQVZwewzMMz7YVR16ldg50IFuAlfA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "11.2.14", + "@angular/core": "11.2.14", + "@angular/platform-browser": "11.2.14", + "rxjs": "^6.5.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.10", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/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==", + "dev": true + }, + "node_modules/@babel/generator": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.12.11", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/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/@babel/helper-create-class-features-plugin": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz", + "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "regexpu-core": "^4.7.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-wrap-function": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/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==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", + "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", + "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", + "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.7", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", + "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", + "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", + "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", + "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.14.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", + "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "semver": "^5.5.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", + "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", + "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.12.7", + "@babel/helper-compilation-targets": "^7.12.5", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.11", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.7", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.11", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.7", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.10", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.11", + "core-js-compat": "^3.8.0", + "semver": "^5.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/@babel/template": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" + } + }, + "node_modules/@babel/traverse": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.7", + "@babel/types": "^7.14.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/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==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz", + "integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.1", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/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==", + "dev": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/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==", + "dev": true + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", + "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", + "dev": true, + "dependencies": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.3", + "loader-utils": "^2.0.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.7.0" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@microsoft/signalr": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-3.0.1.tgz", + "integrity": "sha512-tRhqAmf5SyK02VXM6noj6DjSgt0i8yDqspHdLqdqsSrjMh4/inrwjI/BqLVE8zLD3mHp+eGHeSnlLTUVe024vA==", + "dependencies": { + "eventsource": "^1.0.7", + "request": "^2.88.0", + "ws": "^6.0.0" + } + }, + "node_modules/@ng-bootstrap/ng-bootstrap": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-8.0.4.tgz", + "integrity": "sha512-EdxTwOPOtlvfnwrglPniulmzdnXdXH3lTGaGAY1HrYRvdtGg6wicRvl+BvwVE/3Qik5NPkOWMVghUHpv3evIYg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "^10.0.0", + "@angular/core": "^10.0.0", + "@angular/forms": "^10.0.0", + "@angular/localize": "^10.0.0", + "rxjs": "^6.5.5" + } + }, + "node_modules/@ngtools/webpack": { + "version": "11.2.19", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.2.19.tgz", + "integrity": "sha512-HwLHA6ZrLSk7VHm5Bv3a8ljM6uU8+/670u2fKfMFwM4UQ42+yTFihwfFKLWQIcawBOlVCaUosr6o1xmeSquAqA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.2.19", + "enhanced-resolve": "5.7.0", + "webpack-sources": "2.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^11.0.0 || ^11.2.0-next", + "typescript": "~4.0.0 || ~4.1.0", + "webpack": "^4.0.0" + } + }, + "node_modules/@ngtools/webpack/node_modules/@angular-devkit/core": { + "version": "11.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.19.tgz", + "integrity": "sha512-kvS0QXDYDatLyf0NYv2sahPYD7kya4g5GpQAV1ddjjLmEVeZssHt+Xfk2tzrkzYzqRMiyspx3HPPrrOnMUAFhQ==", + "dev": true, + "dependencies": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@ngtools/webpack/node_modules/enhanced-resolve": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", + "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@ngtools/webpack/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@ngtools/webpack/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@ngtools/webpack/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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==", + "dev": true + }, + "node_modules/@npmcli/git": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", + "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^6.1.1", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + } + }, + "node_modules/@npmcli/git/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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/npm-package-arg": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", + "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/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==", + "dev": true, + "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/@npmcli/git/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==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/git/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "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==", + "dev": true, + "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/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==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "infer-owner": "^1.0.4" + } + }, + "node_modules/@npmcli/run-script": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.5.tgz", + "integrity": "sha512-NQspusBCpTjNwNRFMtz2C5MxoxyzlbuJ4YEhxAKrIonTiirKDtatsZictx9RgamQIx6+QuHMNmPl0wQdoESs9A==", + "dev": true, + "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/@npmcli/run-script/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==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@popperjs/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.0.0.tgz", + "integrity": "sha512-bN4670c4wr7RAOWTaf+h5KpC8al3h5fZSXqffakZrxZA01aKulM3rwIsU7qutrnYWw/nC1W06buOms/Rh+ZEDA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@schematics/angular": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-11.2.14.tgz", + "integrity": "sha512-nErn5BFYp4HB7mOkt23kF+dyM6zPxolejM8eXQ5vd/rdhcc6ROaMZ0EmeEAWkfqB3+vqaSDz/D2Nm/IjJlyW/Q==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.2.14", + "@angular-devkit/schematics": "11.2.14", + "jsonc-parser": "3.0.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/update": { + "version": "0.1102.14", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1102.14.tgz", + "integrity": "sha512-OsWuC0iyNjpST1+hVUUZAegXAFpEFpS5uKYSQF3jsbyw8XHx7oA5/HbEwyr2WkX2EdV1tKrDLz6BrD5b8W6EYw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "11.2.14", + "@angular-devkit/schematics": "11.2.14", + "@yarnpkg/lockfile": "1.1.0", + "ini": "2.0.0", + "npm-package-arg": "^8.0.0", + "pacote": "11.2.4", + "semver": "7.3.4", + "semver-intersect": "1.4.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": "^6.11.0 || ^7.5.6", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/update/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@schematics/update/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@schematics/update/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@schematics/update/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/core-js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.0.tgz", + "integrity": "sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/hammerjs": { + "version": "2.0.35", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.35.tgz", + "integrity": "sha512-4mUIMSZ2U4UOWq1b+iV7XUTE4w+Kr3x+Zb/Qz5ROO6BTZLw2c8/ftjq0aRgluguLs4KRuBnrOy/s389HVn1/zA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.8", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", + "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.11.tgz", + "integrity": "sha512-S6pvzQDvMZHrkBz2Mcn/8Du7cpr76PlRJBAoHnSDNbulULsH5dp0Gns+WRyNX5LHejz/ljxK4/vIHK/caHt6SQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "12.20.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.15.tgz", + "integrity": "sha512-F6S4Chv4JicJmyrwlDkxUdGNSplsQdGwp1A0AJloEVDirWdZOAiRHhovDlsFkKUrquUXhz1imJhXHsf59auyAg==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/protractor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/protractor/-/protractor-4.0.0.tgz", + "integrity": "sha1-EZFYRbONSD9wYNdOyOLu7kNXOZk=", + "deprecated": "This is a stub types definition for Protractor (https://github.com/angular/protractor). Protractor provides its own type definitions, so you don't need @types/protractor installed!", + "dev": true, + "dependencies": { + "protractor": "*" + } + }, + "node_modules/@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/retry": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + }, + "node_modules/@types/selenium-webdriver": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz", + "integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==", + "dev": true + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "node_modules/@types/webpack-sources": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", + "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + } + }, + "node_modules/@types/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@types/ws": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.2.tgz", + "integrity": "sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" + }, + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" + }, + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dependencies": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "peerDependencies": { + "acorn": "^6.0.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "engines": { + "node": ">=0.3.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/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==", + "dev": true + }, + "node_modules/agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/agentkeepalive/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agentkeepalive/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==", + "dev": true + }, + "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" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", + "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "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/ajv-formats/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/ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "peerDependencies": { + "ajv": "^6.0.0" + } + }, + "node_modules/alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "node_modules/ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "dependencies": { + "string-width": "^2.0.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-align/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/ansi-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "devOptional": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argparse/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "dependencies": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "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=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "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=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dependencies": { + "inherits": "2.0.1" + } + }, + "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=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "devOptional": true + }, + "node_modules/async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.4.tgz", + "integrity": "sha512-DCCdUQiMD+P/as8m3XkeTUkUKuuRqLGcwD0nll7wevhqoJfMRpJlkFd1+MQh1pvupjiQuip42lc/VFvfUTMSKw==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.1", + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "fraction.js": "^4.0.13", + "normalize-range": "^0.1.2", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "node_modules/axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "dependencies": { + "ast-types-flow": "0.0.7" + } + }, + "node_modules/babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/babel-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/babel-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/babel-loader/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/babel-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/babel-loader/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==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/babel-loader/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/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "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=", + "optional": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "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/bl/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/bl/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/blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "blocking-proxy": "built/lib/bin.js" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "dependencies": { + "bytes": "3.1.1", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser/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/body-parser/node_modules/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/body-parser/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "node_modules/bootstrap": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz", + "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + }, + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.0" + } + }, + "node_modules/boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "dependencies": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/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/boxen/node_modules/chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/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/boxen/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/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/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/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/browserify-sign/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/browserify-sign/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/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/browserstack": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz", + "integrity": "sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + } + }, + "node_modules/browserstack/node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/browserstack/node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "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==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "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==" + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "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.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "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/cacache/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-base/node_modules/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==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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" + } + }, + "node_modules/camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001239", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz", + "integrity": "sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "node_modules/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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "devOptional": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "~5.1.2", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/chokidar/node_modules/fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "bundleDependencies": [ + "node-pre-gyp" + ], + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/abbrev": { + "version": "1.1.1", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/debug": { + "version": "3.2.6", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "inBundle": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/detect-libc": { + "version": "1.0.3", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "inBundle": true, + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/fs-minipass": { + "version": "1.2.7", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "inBundle": true, + "optional": true, + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "inBundle": true, + "optional": true, + "dependencies": { + "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" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/glob": { + "version": "7.1.6", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "inBundle": true, + "optional": true, + "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/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/ignore-walk": { + "version": "3.0.3", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "inBundle": true, + "optional": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "inBundle": true, + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/inherits": { + "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/ini": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.6.tgz", + "integrity": "sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg==", + "inBundle": true, + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "inBundle": true, + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/minipass": { + "version": "2.9.0", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "inBundle": true, + "optional": true, + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/minizlib": { + "version": "1.3.3", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "inBundle": true, + "optional": true, + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/mkdirp": { + "version": "0.5.1", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "inBundle": true, + "optional": true, + "dependencies": { + "minimist": "1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/mkdirp/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/ms": { + "version": "2.1.2", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/needle": { + "version": "2.4.0", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "inBundle": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/node-pre-gyp": { + "version": "0.14.0", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "deprecated": "Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future", + "inBundle": true, + "optional": true, + "dependencies": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/node-pre-gyp/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/node-pre-gyp/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" + } + ], + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/node-pre-gyp/node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "inBundle": true, + "optional": true, + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/node-pre-gyp/node_modules/tar/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==", + "inBundle": true, + "optional": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/nopt": { + "version": "4.0.1", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "inBundle": true, + "optional": true, + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/npm-bundled": { + "version": "1.1.1", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "inBundle": true, + "optional": true, + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/npm-packlist": { + "version": "1.4.7", + "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", + "inBundle": true, + "optional": true, + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/npmlog": { + "version": "4.1.2", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "inBundle": true, + "optional": true, + "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/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "inBundle": true, + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/os-tmpdir": { + "version": "1.0.2", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/osenv": { + "version": "0.1.5", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "inBundle": true, + "optional": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/process-nextick-args": { + "version": "2.0.1", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/rc": { + "version": "1.2.8", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "inBundle": true, + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.6", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/rc/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "inBundle": true, + "optional": true, + "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/chokidar/node_modules/fsevents/node_modules/rimraf": { + "version": "2.7.1", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "inBundle": true, + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "inBundle": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/signal-exit": { + "version": "3.0.2", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "inBundle": true, + "optional": true, + "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/chokidar/node_modules/fsevents/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=", + "inBundle": true, + "optional": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/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=", + "inBundle": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/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==", + "inBundle": true, + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/node_modules/fsevents/node_modules/yallist": { + "version": "3.1.1", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "inBundle": true, + "optional": true + }, + "node_modules/chokidar/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==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/circular-dependency-plugin": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz", + "integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "webpack": ">=4.0.1" + } + }, + "node_modules/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==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/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" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/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/cliui/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/cliui/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/cliui/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/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==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codelyzer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz", + "integrity": "sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==", + "dev": true, + "dependencies": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "peerDependencies": { + "@angular/compiler": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next", + "@angular/core": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next", + "tslint": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/compiler": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", + "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", + "dev": true, + "peerDependencies": { + "tslib": "^1.10.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", + "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", + "dev": true, + "peerDependencies": { + "rxjs": "^6.5.3", + "tslib": "^1.10.0", + "zone.js": "~0.10.2" + } + }, + "node_modules/codelyzer/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/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/colord": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.0.1.tgz", + "integrity": "sha512-vm5YpaWamD0Ov6TSG0GGmUIwstrWcfKQV/h2CmbR7PbNu41+qdB5PW9lpzhjedrpm08uuYvcXi0Oel1RLZIJuA==", + "dev": true + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "node_modules/component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "node_modules/compressible": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz", + "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==", + "dependencies": { + "mime-db": ">= 1.38.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "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=" + }, + "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==", + "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/configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "dependencies": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/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": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "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=", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/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/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/copy-anything": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz", + "integrity": "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ==", + "dev": true, + "dependencies": { + "is-what": "^3.12.0" + } + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.3.2.tgz", + "integrity": "sha512-MgJ1uouLIbDg4ST1GzqrGQyKoXY5iPqi6fghFqarijam7FQcBa/r6Rg0VkoIuzx75Xq8iAMghyOueMkWUQ5OaA==", + "dev": true, + "dependencies": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/copy-webpack-plugin/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/copy-webpack-plugin/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/copy-webpack-plugin/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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin/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==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/copy-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/core-js": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.14.0.tgz", + "integrity": "sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.1.tgz", + "integrity": "sha512-xGhzYMX6y7oEGQGAJmP2TmtBLvR4nZmRGEcFa3ubHOq5YEp51gGN9AovVa0AoujGZIq+Wm6dISiYyGNfdflYww==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "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=" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/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=", + "dev": true, + "dependencies": { + "capture-stack-trace": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/critters": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.12.tgz", + "integrity": "sha512-ujxKtKc/mWpjrOKeaACTaQ1aP0O31M0ZPWhfl85jZF1smPU4Ivb9va5Ox2poif4zVJQQo0LCFlzGtEZAsCAPcw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^4.1.3", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "postcss": "^8.3.7", + "pretty-bytes": "^5.3.0" + } + }, + "node_modules/critters/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/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/critters/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/critters/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/critters/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/critters/node_modules/postcss": { + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", + "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", + "dev": true, + "dependencies": { + "nanoid": "^3.2.0", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/critters/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/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/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-color-names": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-1.0.1.tgz", + "integrity": "sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.0.3.tgz", + "integrity": "sha512-52P95mvW1SMzuRZegvpluT6yEv0FqQusydKQPZsNN5Q7hh8EwQvN8E2nwuJ16BBvNN6LcoIZXu/Bk58DAhrrxw==", + "dev": true, + "dependencies": { + "timsort": "^0.3.0" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-loader": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.0.1.tgz", + "integrity": "sha512-cXc2ti9V234cq7rJzFKhirb2L2iPy8ZjALeVJAozXYz9te3r4eqLSixNAbMDJSgJEQywqXzs8gonxaboeKqwiw==", + "dev": true, + "dependencies": { + "camelcase": "^6.2.0", + "cssesc": "^3.0.0", + "icss-utils": "^5.0.0", + "loader-utils": "^2.0.0", + "postcss": "^8.1.4", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/css-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/css-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css-loader/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" + } + }, + "node_modules/css-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/css-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/css-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/css-loader/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-loader/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "dependencies": { + "css": "^2.0.0" + } + }, + "node_modules/css-parse/node_modules/css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "node_modules/css-parse/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "dependencies": { + "through": "X.X.X" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.2.tgz", + "integrity": "sha512-8JK3EnPsjQsULme9/e5M2hF564f/480hwsdcHvQ7ZtAIMfQ1O3SCfs+b8Mjf5KJxhYApyRshR2QSovEJi2K72Q==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "cssnano-preset-default": "^5.0.1", + "is-resolvable": "^1.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.1" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.3.tgz", + "integrity": "sha512-qo9tX+t4yAAZ/yagVV3b+QBKeLklQbmgR3wI7mccrDcR+bEk9iHgZN1E7doX68y9ThznLya3RDmR+nc7l6/2WQ==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^6.0.3", + "cssnano-utils": "^2.0.1", + "postcss-calc": "^8.0.0", + "postcss-colormin": "^5.2.0", + "postcss-convert-values": "^5.0.1", + "postcss-discard-comments": "^5.0.1", + "postcss-discard-duplicates": "^5.0.1", + "postcss-discard-empty": "^5.0.1", + "postcss-discard-overridden": "^5.0.1", + "postcss-merge-longhand": "^5.0.2", + "postcss-merge-rules": "^5.0.2", + "postcss-minify-font-values": "^5.0.1", + "postcss-minify-gradients": "^5.0.1", + "postcss-minify-params": "^5.0.1", + "postcss-minify-selectors": "^5.1.0", + "postcss-normalize-charset": "^5.0.1", + "postcss-normalize-display-values": "^5.0.1", + "postcss-normalize-positions": "^5.0.1", + "postcss-normalize-repeat-style": "^5.0.1", + "postcss-normalize-string": "^5.0.1", + "postcss-normalize-timing-functions": "^5.0.1", + "postcss-normalize-unicode": "^5.0.1", + "postcss-normalize-url": "^5.0.2", + "postcss-normalize-whitespace": "^5.0.1", + "postcss-ordered-values": "^5.0.2", + "postcss-reduce-initial": "^5.0.1", + "postcss-reduce-transforms": "^5.0.1", + "postcss-svgo": "^5.0.2", + "postcss-unique-selectors": "^5.0.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz", + "integrity": "sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", + "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "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/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=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "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==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/default-gateway/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" + } + }, + "node_modules/default-gateway/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "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/default-gateway/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway/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/default-gateway/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/default-gateway/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/default-gateway/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/default-gateway/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/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/del/node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/del/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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "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" + } + }, + "node_modules/dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "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/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domino": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz", + "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==" + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "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==", + "dev": true, + "dependencies": { + "is-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/electron-to-chromium": { + "version": "1.3.757", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.757.tgz", + "integrity": "sha512-kP0ooyrvavDC+Y9UG6G/pUVxfRNM2VTJwtLQLvgsJeyf1V+7shMCb68Wj0/TETmfx8dWv9pToGkVT39udE87wQ==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/elliptic/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/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==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "optional": true, + "dependencies": { + "iconv-lite": "~0.4.13" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", + "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "dependencies": { + "@socket.io/base64-arraybuffer": "~1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/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==", + "dev": true + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/enhanced-resolve/node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/enhanced-resolve/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "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==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "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-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "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=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz", + "integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.2.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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/eslint/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/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/eslint/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/eslint/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/eslint/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==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/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/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/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/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/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==", + "dev": true + }, + "node_modules/eslint/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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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/eslint/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/espree": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "dev": true, + "dependencies": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "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==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/eventsource": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", + "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "dependencies": { + "original": "^1.0.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/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/express/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/express/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/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/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "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==" + }, + "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" + } + }, + "node_modules/fast-glob/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" + } + }, + "node_modules/fast-glob/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/fast-glob/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/fast-glob/node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/fast-glob/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/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==" + }, + "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 + }, + "node_modules/fast-xml-parser": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz", + "integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==", + "bin": { + "xml2js": "cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "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" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, + "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/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, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz", + "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==", + "dependencies": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0 < 7.0.0 || >= 8.9.0" + }, + "peerDependencies": { + "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/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==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-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==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "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/find-up/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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=", + "engines": { + "node": ">=0.10.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz", + "integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/front-matter": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-2.1.2.tgz", + "integrity": "sha1-91mDufL0E75ljJPf172M5AePXNs=", + "dev": true, + "dependencies": { + "js-yaml": "^3.4.6" + } + }, + "node_modules/fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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 + }, + "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 + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "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-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": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "engines": { + "node": ">=0.10.0" + } + }, + "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/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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": "*" + } + }, + "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/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/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/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "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/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "dependencies": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gonzales-pe-sl": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/gonzales-pe-sl/-/gonzales-pe-sl-4.2.3.tgz", + "integrity": "sha1-aoaLw4BkXxQf7rBCxvl/zHG1n+Y=", + "dev": true, + "dependencies": { + "minimist": "1.2.5" + }, + "bin": { + "gonzales": "bin/gonzales.js" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/got": { + "version": "6.7.1", + "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "node_modules/handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==" + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/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=", + "dev": true + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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=", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/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/hash-base/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/hash-base/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/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "node_modules/hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" + }, + "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==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", + "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/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==", + "dev": true + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz", + "integrity": "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/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" + } + }, + "node_modules/http-proxy-middleware/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/http-proxy-middleware/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/http-proxy-middleware/node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/http-proxy-middleware/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/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "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-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "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==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/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==", + "dev": true + }, + "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/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "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/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "node_modules/ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "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/import-fresh/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/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "dependencies": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/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==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/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==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/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==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ini": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.6.tgz", + "integrity": "sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg==", + "dev": true, + "engines": { + "node": "*" + } + }, + "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/inquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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/inquirer/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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/inquirer/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/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/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/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/inquirer/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/inquirer/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/inquirer/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-ip/node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-ip/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "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/internal-ip/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==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "devOptional": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "dependencies": { + "ci-info": "^1.5.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "dependencies": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "node_modules/is-color-stop/node_modules/css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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": ">=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": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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=", + "dev": true + }, + "node_modules/is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "node_modules/is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-svg": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.1.tgz", + "integrity": "sha512-h2CGs+yPUyvkgTJQS9cJzo9lYK06WgRiXUqBBHtglSzVKAuH4/oWsqk7LGfbSa1hGk9QcZ0SyQtVggvBA8LZXA==", + "dependencies": { + "fast-xml-parser": "^3.19.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "engines": { + "node": ">=4" + } + }, + "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.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true, + "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/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "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/istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/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/jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "dependencies": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "bin": { + "jasmine": "bin/jasmine.js" + } + }, + "node_modules/jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, + "node_modules/jasmine-spec-reporter": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz", + "integrity": "sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + } + }, + "node_modules/jasmine/node_modules/jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + }, + "node_modules/jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true, + "engines": { + "node": ">= 6.9.x" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/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/jest-worker/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/jquery": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.0.tgz", + "integrity": "sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ==" + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "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=", + "optional": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/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==" + }, + "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==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "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-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-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": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "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=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jszip": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "node_modules/karma": { + "version": "6.3.16", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.16.tgz", + "integrity": "sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==", + "dev": true, + "dependencies": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "colors": "1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-cli": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma-cli/-/karma-cli-2.0.0.tgz", + "integrity": "sha512-1Kb28UILg1ZsfqQmeELbPzuEb5C6GZJfVIk0qOr8LNYQuYWmAaqP16WpbpKEjhejDrDYyYOwwJXSZO6u7q5Pvw==", + "dev": true, + "dependencies": { + "resolve": "^1.3.3" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/karma-jasmine": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.1.tgz", + "integrity": "sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==", + "dev": true, + "dependencies": { + "jasmine-core": "^3.6.0" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "karma": "*" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", + "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", + "dev": true, + "peerDependencies": { + "jasmine-core": ">=3.8", + "karma": ">=0.9", + "karma-jasmine": ">=1.1" + } + }, + "node_modules/karma-jasmine/node_modules/jasmine-core": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.7.1.tgz", + "integrity": "sha512-DH3oYDS/AUvvr22+xUBW62m1Xoy7tUlY1tsxKEJvl5JeJ7q8zd1K5bUwiOxdH+erj6l2vAMM3hV25Xs9/WrmuQ==", + "dev": true + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/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/karma/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/karma/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" + } + }, + "node_modules/karma/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/karma/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/karma/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/karma/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/karma/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==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "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/karma/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/karma/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/karma/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==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/karma/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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/karma/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/karma/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==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/karma/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/karma/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/killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "node_modules/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/known-css-properties": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.3.0.tgz", + "integrity": "sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ==", + "dev": true + }, + "node_modules/latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "dependencies": { + "package-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", + "integrity": "sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^1.10.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^2.5.2", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-7.3.0.tgz", + "integrity": "sha512-Mi8915g7NMaLlgi77mgTTQvK022xKRQBIVDSyfl3ErTuBhmZBQab0mjeJjNNqGbdR+qrfTleKXqbGI4uEFavxg==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/less-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/less-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/less-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/less-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/less-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/less/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "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/license-webpack-plugin": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.11.tgz", + "integrity": "sha512-0iVGoX5vx0WDy8dmwTTpOOMYiGqILyUbDeVMFH52AjgBlS58lHwOlFMSoqg5nY8Kxl6+FRKyUZY/UdlQaOyqDw==", + "dev": true, + "dependencies": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + } + }, + "node_modules/license-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/license-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "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=", + "dev": true + }, + "node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dependencies": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/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" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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/log-symbols/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/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==" + }, + "node_modules/log-symbols/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/log-symbols/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/log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/log4js/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/log4js/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==", + "dev": true + }, + "node_modules/loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, + "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==", + "dev": true, + "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/make-fetch-happen/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/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==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "dependencies": { + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.5.tgz", + "integrity": "sha512-tvmzcwqJJXau4OQE5vT72pRT18o2zF+tQJp8CWchqvfQnTlflkzS+dANYcRdyPRWUWRkfmeNTKltx0NZI/b5dQ==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "webpack-sources": "^1.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "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.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/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/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/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/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": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + }, + "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/nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "optional": true + }, + "node_modules/nanoid": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/needle": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", + "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/needle/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, + "optional": true + }, + "node_modules/negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/ngx-toastr": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-13.2.1.tgz", + "integrity": "sha512-UAzp7/xWK9IXA2LsOmhpaaIGCqscvJokoQpBNpAMrjEkDeSlFf8PWQAuQY795KW0mJb3qF9UG/s23nsXfMYKmg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=10.0.0-0", + "@angular/core": ">=10.0.0-0", + "@angular/platform-browser": ">=10.0.0-0" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.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==", + "dev": true, + "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/node-gyp/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "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/node-gyp/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/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", + "dev": true, + "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/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/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==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/node-libs-browser/node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "node_modules/nodemon": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz", + "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "chokidar": "^2.1.8", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^2.5.0" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/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/nodemon/node_modules/pstree.remy": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", + "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==", + "dev": true + }, + "node_modules/nodemon/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/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "devOptional": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/normalize.css": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", + "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-install-checks/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "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==", + "dev": true + }, + "node_modules/npm-package-arg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.0.tgz", + "integrity": "sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig==", + "dev": true, + "dependencies": { + "hosted-git-info": "^3.0.6", + "semver": "^7.0.0", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/npm-packlist": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz", + "integrity": "sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==", + "dev": true, + "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-packlist/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "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/npm-pick-manifest": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.0.tgz", + "integrity": "sha512-ygs4k6f54ZxJXrzT0x34NybRlLeZ4+6nECAIbr2i0foTnijtS1TJiyzpqtuUAJOps/hO0tNDr8fRV5g+BtRlTw==", + "dev": true, + "dependencies": { + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.0.0", + "semver": "^7.0.0" + } + }, + "node_modules/npm-pick-manifest/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "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==", + "dev": true, + "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-registry-fetch/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-registry-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "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=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-watch": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/npm-watch/-/npm-watch-0.5.0.tgz", + "integrity": "sha512-Rww9iNlmsVhcpUTDoKfUlbfmEtTZ3T3gUZBW/VjuL4ct/nwV0XlwBDOxR0ECJ/cLF8PF1wPVa/IrinI6K5ECQQ==", + "dev": true, + "dependencies": { + "nodemon": "^1.18.7", + "through2": "^2.0.0" + }, + "bin": { + "npm-watch": "cli.js" + } + }, + "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==", + "dev": true, + "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.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "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=", + "dev": true, + "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-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "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/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/open": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.0.tgz", + "integrity": "sha512-PGoBCX/lclIWlpS/R2PQuIR4NJoXh6X5AwVzE7WXnWRGvHg7+4TBCgsujUgiPpm0K1y4qvQeWnCWVTpTKZBtvA==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "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/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/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" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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/ora/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/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==" + }, + "node_modules/ora/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/ora/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/ora/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/original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dependencies": { + "url-parse": "^1.4.3" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "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=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/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-retry": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", + "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "dependencies": { + "@types/retry": "^0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "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/package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "dependencies": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pacote": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.2.4.tgz", + "integrity": "sha512-GfTeVQGJ6WyBQbQD4t3ocHbyOmTQLmWjkCKSZPmKiGFKYKNUaM5U2gbLzUW8WG1XmS9yQFnsTFA0k3o1+q4klQ==", + "dev": true, + "dependencies": { + "@npmcli/git": "^2.0.1", + "@npmcli/installed-package-contents": "^1.0.5", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.3.0", + "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": "^1.1.1", + "read-package-json-fast": "^1.1.3", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.1.0" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pacote/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pacote/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "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/parent-module/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, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "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==", + "dev": true, + "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/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", + "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1", + "parse5-sax-parser": "^6.0.1" + } + }, + "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==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", + "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "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/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-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "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/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "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/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "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/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "dev": true, + "dependencies": { + "ts-pnp": "^1.1.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/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==" + }, + "node_modules/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=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-calc": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz", + "integrity": "sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.0.tgz", + "integrity": "sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz", + "integrity": "sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz", + "integrity": "sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz", + "integrity": "sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz", + "integrity": "sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz", + "integrity": "sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-import": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.0.0.tgz", + "integrity": "sha512-gFDDzXhqr9ELmnLHgCC3TbGfA6Dm/YMb/UN8/f7Uuq4fL7VTk2vOIj6hwINEwbokEmp123bLD7a5m+E+KIetRg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-loader": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.2.0.tgz", + "integrity": "sha512-mqgScxHqbiz1yxbnNcPdKYo/6aVt+XExURmEbQlviFVWogDbM4AJ0A/B+ZBpYsJrTRxKw7HyRazg9x0Q9SWwLA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/postcss-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/postcss-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/postcss-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/postcss-loader/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-loader/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/postcss-merge-longhand": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz", + "integrity": "sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw==", + "dev": true, + "dependencies": { + "css-color-names": "^1.0.1", + "postcss-value-parser": "^4.1.0", + "stylehacks": "^5.0.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz", + "integrity": "sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^2.0.1", + "postcss-selector-parser": "^6.0.5", + "vendors": "^1.0.3" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz", + "integrity": "sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.1.tgz", + "integrity": "sha512-odOwBFAIn2wIv+XYRpoN2hUV3pPQlgbJ10XeXPq8UY2N+9ZG42xu45lTn/g9zZ+d70NKSQD6EOi6UiCMu3FN7g==", + "dev": true, + "dependencies": { + "cssnano-utils": "^2.0.1", + "is-color-stop": "^1.1.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz", + "integrity": "sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.2", + "browserslist": "^4.16.0", + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz", + "integrity": "sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.2", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz", + "integrity": "sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz", + "integrity": "sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ==", + "dev": true, + "dependencies": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz", + "integrity": "sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz", + "integrity": "sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w==", + "dev": true, + "dependencies": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz", + "integrity": "sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz", + "integrity": "sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q==", + "dev": true, + "dependencies": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz", + "integrity": "sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz", + "integrity": "sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ==", + "dev": true, + "dependencies": { + "is-absolute-url": "^3.0.3", + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz", + "integrity": "sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz", + "integrity": "sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ==", + "dev": true, + "dependencies": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz", + "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz", + "integrity": "sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA==", + "dev": true, + "dependencies": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", + "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.2.tgz", + "integrity": "sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.1.0", + "svgo": "^2.3.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz", + "integrity": "sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.2", + "postcss-selector-parser": "^6.0.5", + "uniqs": "^2.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "node_modules/postcss/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true, + "engines": { + "node": ">=0.10.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==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "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": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "dependencies": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/promise-retry/node_modules/err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "node_modules/promise-retry/node_modules/retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/protractor": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "dev": true, + "dependencies": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "bin": { + "protractor": "bin/protractor", + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=10.13.x" + } + }, + "node_modules/protractor/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/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/protractor/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/protractor/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/protractor/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/protractor/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/protractor/node_modules/del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "dependencies": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/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/protractor/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/protractor/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/protractor/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/webdriver-manager": { + "version": "12.1.8", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.8.tgz", + "integrity": "sha512-qJR36SXG2VwKugPcdwhaqcLQOD7r8P2Xiv9sfNbfZrKBnX243iAkOueX1yAmeNgIKhJ3YAT/F2gq6IiEZzahsg==", + "dev": true, + "dependencies": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "bin": { + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/protractor/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/protractor/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/protractor/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/protractor/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/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "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/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "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/q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "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=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "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/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "dependencies": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body/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/raw-body/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/raw-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/raw-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/raw-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/raw-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/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=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-1.2.2.tgz", + "integrity": "sha512-39DbPJjkltEzfXJXB6D8/Ir3GFOU2YbSKa2HaB/Y3nKrc/zY+0XrALpID6/13ezWyzqvOHrBbR4t4cjQuTdBVQ==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "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/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "devOptional": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", + "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "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=", + "devOptional": true + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "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.0", + "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.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 4" + } + }, + "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/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "node_modules/resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.5" + } + }, + "node_modules/resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/resolve-url-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/resolve-url-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true, + "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/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "node_modules/rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "node_modules/rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dependencies": { + "glob": "^7.0.5" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rollup": { + "version": "2.38.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.4.tgz", + "integrity": "sha512-B0LcJhjiwKkTl79aGVF/u5KdzsH8IylVfV56Ut6c9ouWLJcUK17T83aZBetNYSnZtXf2OHD4+2PbmRW+Fp5ulg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "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==", + "dev": true, + "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/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dependencies": { + "aproba": "^1.1.1" + } + }, + "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/rxjs-compat": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs-compat/-/rxjs-compat-6.6.7.tgz", + "integrity": "sha512-szN4fK+TqBPOFBcBcsR0g2cmTTUF/vaFEOZNuSdfU8/pGFnNmmn2u8SystYXG1QMrjOPBc6XTKHMVfENDf6hHw==" + }, + "node_modules/rxjs-tslint": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/rxjs-tslint/-/rxjs-tslint-0.1.8.tgz", + "integrity": "sha512-4MNcco1pugjNyjkUkvJ9ngJSMCuwmyc1g6EkEYzlTK0PrZxm8xVaBeBz5aPLE3AzldQbYkOErOVAayUlzQkjAg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.0", + "tslint": "^5.9.1", + "tsutils": "^2.25.0", + "typescript": ">=2.8.3", + "yargs": "^15.3.1" + }, + "bin": { + "rxjs-5-to-6-migrate": "bin/rxjs-5-to-6-migrate" + }, + "peerDependencies": { + "tslint": "^5.0.0", + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev" + } + }, + "node_modules/rxjs-tslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rxjs-tslint/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/rxjs-tslint/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/rxjs-tslint/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/rxjs-tslint/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/rxjs-tslint/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/rxjs-tslint/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/rxjs-tslint/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/rxjs-tslint/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/rxjs-tslint/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rxjs-tslint/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/rxjs-tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/rxjs-tslint/node_modules/tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" + } + }, + "node_modules/rxjs-tslint/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/rxjs-tslint/node_modules/wrap-ansi/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/rxjs-tslint/node_modules/wrap-ansi/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/rxjs-tslint/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/rxjs-tslint/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/rxjs-tslint/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/rxjs/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/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/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dependencies": { + "ret": "~0.1.10" + } + }, + "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/sass": { + "version": "1.32.6", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.32.6.tgz", + "integrity": "sha512-1bcDHDcSqeFtMr0JXI3xc/CXX6c4p0wHHivJdru8W7waM7a1WjKMm4m/Z5sY7CbVw4Whi2Chpcw6DFfSWwGLzQ==", + "dev": true, + "dependencies": { + "chokidar": ">=2.0.0 <4.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/sass-lint": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sass-lint/-/sass-lint-1.13.1.tgz", + "integrity": "sha512-DSyah8/MyjzW2BWYmQWekYEKir44BpLqrCFsgs9iaWiVTcwZfwXHF586hh3D1n+/9ihUNMfd8iHAyb9KkGgs7Q==", + "dev": true, + "dependencies": { + "commander": "^2.8.1", + "eslint": "8.10.0", + "front-matter": "2.1.2", + "fs-extra": "^3.0.1", + "glob": "^7.0.0", + "globule": "^1.0.0", + "gonzales-pe-sl": "^4.2.3", + "js-yaml": "^3.5.4", + "known-css-properties": "^0.3.0", + "lodash.capitalize": "^4.1.0", + "lodash.kebabcase": "^4.0.0", + "merge": "2.1.1", + "path-is-absolute": "^1.0.0", + "util": "^0.10.3" + }, + "bin": { + "sass-lint": "bin/sass-lint.js" + } + }, + "node_modules/sass-loader": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.1.1.tgz", + "integrity": "sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0", + "sass": "^1.3.0", + "webpack": "^4.36.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/sass-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/sass-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/sass-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/sass-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/sass-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/sass-loader/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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sass-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/sass-loader/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sass-loader/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/saucelabs/node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/saucelabs/node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + }, + "node_modules/selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "dependencies": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "engines": { + "node": ">= 6.9.0" + } + }, + "node_modules/selenium-webdriver/node_modules/tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "dependencies": { + "node-forge": "^1.3.1" + } + }, + "node_modules/selfsigned/node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "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/semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "dependencies": { + "semver": "^5.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "dependencies": { + "semver": "^5.3.0" + } + }, + "node_modules/semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "dependencies": { + "semver": "^5.0.0" + } + }, + "node_modules/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/send/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/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/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/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==" + }, + "node_modules/send/node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/send/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "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/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "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=", + "dev": true + }, + "node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "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/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/shiki": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", + "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "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/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==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/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==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/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==", + "dev": true + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/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==", + "dev": true + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/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==", + "dev": true + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs-client": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.0.tgz", + "integrity": "sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "eventsource": "^1.1.0", + "faye-websocket": "^0.11.4", + "inherits": "^2.0.4", + "url-parse": "^1.5.10" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://tidelift.com/funding/github/npm/sockjs-client" + } + }, + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/sockjs-client/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/sockjs-client/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/sockjs/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/socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "dev": true, + "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.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/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==", + "dev": true + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.1.3.tgz", + "integrity": "sha512-6YHeF+XzDOrT/ycFJNI53cgEsp/tHTMl37hi7uVyqFAlTXW109JazaQCkbc+jjoL2637qkH1amLi+JzrIpt5lA==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.2", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "source-map": "^0.6.1", + "whatwg-mimetype": "^2.3.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/source-map-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/source-map-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/source-map-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/source-map-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/source-map-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/source-map-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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=", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/spdy-transport/node_modules/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==" + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/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/speed-measure-webpack-plugin": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.4.2.tgz", + "integrity": "sha512-AtVzD0bnIy2/B0fWqJpJgmhcrfWFhBlduzSo0uwplr/QvB33ZNZj2NEth3NONgdnZJqicK0W0mSxnLSbsVCDbw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "webpack": "^1 || ^2 || ^3 || ^4 || ^5" + } + }, + "node_modules/speed-measure-webpack-plugin/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/speed-measure-webpack-plugin/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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/speed-measure-webpack-plugin/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/speed-measure-webpack-plugin/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/speed-measure-webpack-plugin/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/speed-measure-webpack-plugin/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/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==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "dashdash": "^1.12.0", + "getpass": "^0.1.1", + "safer-buffer": "^2.0.2" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + }, + "optionalDependencies": { + "bcrypt-pbkdf": "^1.0.0", + "ecc-jsbn": "~0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.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/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "node_modules/streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/streamroller/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/streamroller/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==", + "dev": true + }, + "node_modules/streamroller/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/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/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "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/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.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=", + "dev": true, + "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/style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/style-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/style-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/style-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/style-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/style-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/style-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/stylehacks": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz", + "integrity": "sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.0", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "dependencies": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus-loader": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-4.3.3.tgz", + "integrity": "sha512-PpWB5PnCXUzW4WMYhCvNzAHJBjIBPMXwsdfkkKuA9W7k8OQFMl/19/AQvaWsxz2IptxUlCseyJ6TY/eEKJ4+UQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.4", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "stylus": ">=0.52.4", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/stylus-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/stylus-loader/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/stylus-loader/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/stylus-loader/node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylus-loader/node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/stylus-loader/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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stylus-loader/node_modules/schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/stylus/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "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/stylus/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stylus/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/stylus/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.9.tgz", + "integrity": "sha512-XjLaMNl76o07zqZC/aW4lwegdY07baOH1T8w3AEfrHAdyg/oYO4ctjzEBq9Gy9fEP9oHqLIgvx6zuGDGe+bc8Q==", + "dev": true, + "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/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "dependencies": { + "execa": "^0.7.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", + "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/terser-webpack-plugin/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/terser-webpack-plugin/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/terser-webpack-plugin/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/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/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/terser-webpack-plugin/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/terser/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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=", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dependencies": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "node_modules/thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==" + }, + "node_modules/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=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/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=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/touch/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dependencies": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-helpers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ts-helpers/-/ts-helpers-1.1.2.tgz", + "integrity": "sha1-/Gm+nx87rtAfsaDvjUz+dIgU2DU=", + "dev": true, + "peerDependencies": { + "typescript": ">=1.8.0 <2.1.0 || >=1.9.0-dev || >=2.0.0-dev || || >=2.1.0-dev" + } + }, + "node_modules/ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "dependencies": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/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/tslint/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/tslint/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/tslint/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/tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "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=", + "optional": true + }, + "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-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/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/typedoc": { + "version": "0.22.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.11.tgz", + "integrity": "sha512-pVr3hh6dkS3lPPaZz1fNpvcrqLdtEvXmXayN55czlamSgvEjh+57GUqfhAI1Xsuu/hNHUT1KNSx8LH2wBP/7SA==", + "dev": true, + "dependencies": { + "glob": "^7.2.0", + "lunr": "^2.3.9", + "marked": "^4.0.10", + "minimatch": "^3.0.4", + "shiki": "^0.10.0" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 12.10.0" + }, + "peerDependencies": { + "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x" + } + }, + "node_modules/typedoc/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "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/typescript": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.8.tgz", + "integrity": "sha512-oz1765PN+imfz1MlZzSZPtC/tqcwsCyIYA8L47EkRnRW97ztRk83SzMiWLrnChC0vqoYxSU1fcFUDA5gV/ZiPg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/uglify-js": { + "version": "3.13.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.9.tgz", + "integrity": "sha512-wZbyTQ1w6Y7fHdt8sJnHfSIuWeDgk6B5rCb4E/AM6QNNPbOMIZph21PW5dRB3h7Df0GszN+t7RuUH6sWK5bF0g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "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==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/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==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "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/unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "dependencies": { + "crypto-random-string": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/universal-analytics": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz", + "integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "request": "^2.88.2", + "uuid": "^3.0.0" + } + }, + "node_modules/universal-analytics/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/universal-analytics/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==", + "dev": true + }, + "node_modules/universal-analytics/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", + "dev": true, + "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/universal-analytics/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==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "devOptional": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "dependencies": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-notifier/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/update-notifier/node_modules/chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-notifier/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/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==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-loader": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.1.tgz", + "integrity": "sha512-vugEeXjyYFBCUOpX+ZuaunbK3QXMKaQ3zUnRfIpRBlGkY7QizCnzyyn2ASfcxsvyU3ef+CJppVywnl3Kgf13Gg==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0 < 7.0.0 || >= 8.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/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=", + "dev": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/url-parse/node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "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/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "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/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "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-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=", + "dev": true, + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", + "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", + "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "dev": true + }, + "node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" + } + }, + "node_modules/watchpack/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "optional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/watchpack/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==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "optional": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "optional": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/watchpack/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==", + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/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==", + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/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==", + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/watchpack/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==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/watchpack/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==", + "optional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "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/webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "dependencies": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz", + "integrity": "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.2.2", + "ansi-html-community": "^0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "default-gateway": "^6.0.3", + "del": "^6.0.0", + "express": "^4.17.1", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.0", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "schema-utils": "^4.0.0", + "selfsigned": "^2.0.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "strip-ansi": "^7.0.0", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "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/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/webpack-dev-server/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webpack-dev-server/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-server/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" + } + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + }, + "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-server/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==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-server/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/webpack-dev-server/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/webpack-dev-server/node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server/node_modules/selfsigned": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz", + "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==", + "dependencies": { + "node-forge": "^1.3.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/webpack-dev-server/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/webpack-dev-server/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/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", + "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.1", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "dependencies": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.2.tgz", + "integrity": "sha512-GBWYBoyalbo5YClwWop9qe6Zclp8CIXYGIz12OPclJhIrSplDxs1Ls1JDMH8xBPPrg1T6ISaTW9Y6zOrwEiAzw==", + "dev": true, + "dependencies": { + "webpack-sources": "^1.3.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 2.21.0 < 5", + "webpack": ">= 1.12.11 < 6" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack-subresource-integrity/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-subresource-integrity/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/webpack/node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "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/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/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, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "dependencies": { + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/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/widest-line/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "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/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/worker-plugin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.0.tgz", + "integrity": "sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0" + }, + "peerDependencies": { + "webpack": ">= 4" + } + }, + "node_modules/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, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/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/wrap-ansi/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/wrap-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/wrap-ansi/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/wrap-ansi/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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/xhr2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz", + "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/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/yargs/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==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/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/yargs/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==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/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==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/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/yargs/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/yargs/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/yargs/node_modules/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, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" + } + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.1102.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1102.14.tgz", + "integrity": "sha512-965TVXuBtRb8RySgxRxUEO+YTd7mT0xiqVHSe+MHvMtUCmEE9vwRofFZl6axkK5ri4fiomiMnOVE19aw4spgNQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.2.14", + "rxjs": "6.6.3" + }, + "dependencies": { + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@angular-devkit/build-angular": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1102.19.tgz", + "integrity": "sha512-frI8UyujPB5WV7l9uecH8Ev73TWTV7xEHrwYIKryD/mVmqeg64ILi4/ATPHm1qGFjAH27WWHtzL2vnik5wBlNg==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1102.19", + "@angular-devkit/build-optimizer": "0.1102.19", + "@angular-devkit/build-webpack": "0.1102.19", + "@angular-devkit/core": "11.2.19", + "@babel/core": "7.12.10", + "@babel/generator": "7.12.11", + "@babel/plugin-transform-async-to-generator": "7.12.1", + "@babel/plugin-transform-runtime": "7.12.10", + "@babel/preset-env": "7.12.11", + "@babel/runtime": "7.12.5", + "@babel/template": "7.12.7", + "@discoveryjs/json-ext": "0.5.2", + "@jsdevtools/coverage-istanbul-loader": "3.0.5", + "@ngtools/webpack": "11.2.19", + "ansi-colors": "4.1.1", + "autoprefixer": "10.2.4", + "babel-loader": "8.2.2", + "browserslist": "^4.9.1", + "cacache": "15.0.5", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.2", + "copy-webpack-plugin": "6.3.2", + "core-js": "3.8.3", + "critters": "0.0.12", + "css-loader": "5.0.1", + "cssnano": "5.0.2", + "file-loader": "6.2.0", + "find-cache-dir": "3.3.1", + "glob": "7.1.6", + "https-proxy-agent": "5.0.0", + "inquirer": "7.3.3", + "jest-worker": "26.6.2", + "karma-source-map-support": "1.4.0", + "less": "4.1.1", + "less-loader": "7.3.0", + "license-webpack-plugin": "2.3.11", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "1.3.5", + "minimatch": "3.0.4", + "open": "7.4.0", + "ora": "5.3.0", + "parse5-html-rewriting-stream": "6.0.1", + "pnp-webpack-plugin": "1.6.4", + "postcss": "8.2.15", + "postcss-import": "14.0.0", + "postcss-loader": "4.2.0", + "raw-loader": "4.0.2", + "regenerator-runtime": "0.13.7", + "resolve-url-loader": "4.0.0", + "rimraf": "3.0.2", + "rollup": "2.38.4", + "rxjs": "6.6.3", + "sass": "1.32.6", + "sass-loader": "10.1.1", + "semver": "7.3.4", + "source-map": "0.7.3", + "source-map-loader": "1.1.3", + "source-map-support": "0.5.19", + "speed-measure-webpack-plugin": "1.4.2", + "style-loader": "2.0.0", + "stylus": "0.54.8", + "stylus-loader": "4.3.3", + "terser": "5.5.1", + "terser-webpack-plugin": "4.2.3", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "webpack": "4.44.2", + "webpack-dev-middleware": "3.7.2", + "webpack-dev-server": "3.11.3", + "webpack-merge": "5.7.3", + "webpack-sources": "2.2.0", + "webpack-subresource-integrity": "1.5.2", + "worker-plugin": "5.0.0" + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1102.19.tgz", + "integrity": "sha512-5Opv6H+XyCkuQvQ1jsxw416YqMDPX3dVonMarFGBPLBe8YEXLRTJ60dvmuLsLpWk6ccTd3XiNT7WEJy4ctDc2Q==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.2.19", + "rxjs": "6.6.3" + } + }, + "@angular-devkit/build-webpack": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1102.19.tgz", + "integrity": "sha512-IhN/eeaA2bA1daLTU7YDztxvaS9Hj2J2t889fBYn5xNnM3Z2QqwyncOoj0F0Cumx6tuFtwRSvaKm7+xbbCoJQA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1102.19", + "@angular-devkit/core": "11.2.19", + "rxjs": "6.6.3" + } + }, + "@angular-devkit/core": { + "version": "11.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.19.tgz", + "integrity": "sha512-kvS0QXDYDatLyf0NYv2sahPYD7kya4g5GpQAV1ddjjLmEVeZssHt+Xfk2tzrkzYzqRMiyspx3HPPrrOnMUAFhQ==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "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 + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "core-js": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", + "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "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 + }, + "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==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "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" + } + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "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": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "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" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", + "dev": true, + "requires": { + "ansi-html-community": "0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@angular-devkit/build-optimizer": { + "version": "0.1102.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1102.19.tgz", + "integrity": "sha512-3665mNFwOCqD2HR6Kjrwqh+Jh72h3F7AB88p/oWBvH0GolFCz8JnbwUZJkzTtOsKUw5ZC1Z6b/nbUkCJemxFug==", + "dev": true, + "requires": { + "loader-utils": "2.0.0", + "source-map": "0.7.3", + "tslib": "2.1.0", + "typescript": "4.1.5", + "webpack-sources": "2.2.0" + }, + "dependencies": { + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, + "typescript": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.5.tgz", + "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", + "dev": true + } + } + }, + "@angular-devkit/core": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.14.tgz", + "integrity": "sha512-Ad1fHqLxDwhkQgLPqq9i+G65NSOoIHXQx7ILcSPACKurV3XLS1RO9BgP/BDaqHAG+WslUAPbMStaTzzPm+9dNw==", + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + }, + "dependencies": { + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@angular-devkit/schematics": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-11.2.14.tgz", + "integrity": "sha512-Ol6+0qdGKzuVJm5gCtQr47X0OCihTfAxI4h047cHYhPFIGGPSvkG/QeJMZugflgoobi2k/xcYokOu/VAkRtWbQ==", + "requires": { + "@angular-devkit/core": "11.2.14", + "ora": "5.3.0", + "rxjs": "6.6.3" + }, + "dependencies": { + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "@angular/animations": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-11.2.14.tgz", + "integrity": "sha512-Heq/nNrCmb3jbkusu+BQszOecfFI/31Oxxj+CDQkqqYpBcswk6bOJLoEE472o+vmgxaXbgeflU9qbIiCQhpMFA==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/cli": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-11.2.14.tgz", + "integrity": "sha512-8Ud7vcUK7CKjzT2Ks1glLhleAPIC5ChcrA15XtOb7k+/uMHBkMscP/UKymbVQiBjCJlglbzJoyj8cpVYTZY5KA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1102.14", + "@angular-devkit/core": "11.2.14", + "@angular-devkit/schematics": "11.2.14", + "@schematics/angular": "11.2.14", + "@schematics/update": "0.1102.14", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "4.3.1", + "ini": "2.0.0", + "inquirer": "7.3.3", + "jsonc-parser": "3.0.0", + "npm-package-arg": "8.1.0", + "npm-pick-manifest": "6.1.0", + "open": "7.4.0", + "ora": "5.3.0", + "pacote": "11.2.4", + "resolve": "1.19.0", + "rimraf": "3.0.2", + "semver": "7.3.4", + "symbol-observable": "3.0.0", + "universal-analytics": "0.4.23", + "uuid": "8.3.2" + }, + "dependencies": { + "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 + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.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==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "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" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "symbol-observable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-3.0.0.tgz", + "integrity": "sha512-6tDOXSHiVjuCaasQSWTmHUWn4PuG7qa3+1WT031yTc/swT7+rLiw3GOrFxaH1E3lLP09dH3bVuVDf2gK5rxG3Q==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@angular/common": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-11.2.14.tgz", + "integrity": "sha512-ZSLV/3j7eCTyLf/8g4yBFLWySjiLz3vLJAGWscYoUpnJWMnug1VRu6zoF/COxCbtORgE+Wz6K0uhfS6MziBGVw==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/compiler": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-11.2.14.tgz", + "integrity": "sha512-XBOK3HgA+/y6Cz7kOX4zcJYmgJ264XnfcbXUMU2cD7Ac+mbNhLPKohWrEiSWalfcjnpf5gRfufQrQP7lpAGu0A==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/compiler-cli": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-11.2.14.tgz", + "integrity": "sha512-A7ltnCp03/EVqK/Q3tVUDsokgz5GHW3dSPGl0Csk7Ys5uBB9ibHTmVt4eiXA4jt0+6Bk+mKxwe5BEDqLvwYFAg==", + "dev": true, + "requires": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "fs-extra": "4.0.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^6.3.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.0.0", + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "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 + }, + "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" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "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": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.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 + }, + "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" + } + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "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, + "requires": { + "binary-extensions": "^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==", + "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 + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "@angular/core": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-11.2.14.tgz", + "integrity": "sha512-vpR4XqBGitk1Faph37CSpemwIYTmJ3pdIVNoHKP6jLonpWu+0azkchf0f7oD8/2ivj2F81opcIw0tcsy/D/5Vg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/forms": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-11.2.14.tgz", + "integrity": "sha512-4LWqY6KEIk1AZQFnk+4PJSOCamlD4tumuVN06gO4D0dZo9Cx+GcvW6pM6N0CPubRvPs3sScCnu20WT11HNWC1w==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/language-service": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-11.2.14.tgz", + "integrity": "sha512-3+0F0X4r1WeNOV6VmaMzYnJENPVmLX2/MX3/lugwZPNYKVXl/oGyh/4PB8ktntIj0tnxQuErzqRSeucNStNGRw==", + "dev": true + }, + "@angular/platform-browser": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-11.2.14.tgz", + "integrity": "sha512-fb7b7ss/gRoP8wLAN17W62leMgjynuyjEPU2eUoAAazsG9f2cgM+z3rK29GYncDVyYQxZUZYnjSqvL6GSXx86A==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.2.14.tgz", + "integrity": "sha512-TWTPdFs6iBBcp+/YMsgCRQwdHpWGq8KjeJDJ2tfatGgBD3Gqt2YaHOMST1zPW6RkrmupytTejuVqXzeaKWFxuw==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@angular/platform-server": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-11.2.14.tgz", + "integrity": "sha512-VSJ4FSyMPVCE3EGfD4hIK1fZu+KFYi04uL4Co8vchzBQFpXPFABpCS/lGd7rOyvLnKRmUvl4NGS72gQdS00IUw==", + "requires": { + "domino": "^2.1.2", + "tslib": "^2.0.0", + "xhr2": "^0.2.0" + } + }, + "@angular/router": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-11.2.14.tgz", + "integrity": "sha512-3aYBmj+zrEL9yf/ntIQxHIYaWShZOBKP3U07X2mX+TPMpGlvHDnR7L6bWhQVZwewzMMz7YVR16ldg50IFuAlfA==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/compat-data": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", + "dev": true + }, + "@babel/core": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.10", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "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 + } + } + }, + "@babel/generator": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.11", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz", + "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "regexpu-core": "^4.7.1" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + } + } + }, + "@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", + "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-wrap-function": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-replace-supers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + } + } + }, + "@babel/helpers": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "dev": true, + "requires": { + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "dependencies": { + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + } + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "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==", + "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" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "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" + } + } + } + }, + "@babel/parser": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz", + "integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", + "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", + "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", + "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.7", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.14.5" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", + "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", + "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", + "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", + "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", + "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "semver": "^5.5.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", + "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/preset-env": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", + "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.7", + "@babel/helper-compilation-targets": "^7.12.5", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.11", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.7", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.11", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.7", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.10", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.11", + "core-js-compat": "^3.8.0", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" + } + }, + "@babel/traverse": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.7.tgz", + "integrity": "sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.7", + "@babel/types": "^7.14.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "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 + } + } + }, + "@babel/types": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "to-fast-properties": "^2.0.0" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz", + "integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.1", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "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==", + "dev": true + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "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 + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", + "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", + "dev": true, + "requires": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.3", + "loader-utils": "^2.0.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "@microsoft/signalr": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-3.0.1.tgz", + "integrity": "sha512-tRhqAmf5SyK02VXM6noj6DjSgt0i8yDqspHdLqdqsSrjMh4/inrwjI/BqLVE8zLD3mHp+eGHeSnlLTUVe024vA==", + "requires": { + "eventsource": "^1.0.7", + "request": "^2.88.0", + "ws": "^6.0.0" + } + }, + "@ng-bootstrap/ng-bootstrap": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-8.0.4.tgz", + "integrity": "sha512-EdxTwOPOtlvfnwrglPniulmzdnXdXH3lTGaGAY1HrYRvdtGg6wicRvl+BvwVE/3Qik5NPkOWMVghUHpv3evIYg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngtools/webpack": { + "version": "11.2.19", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.2.19.tgz", + "integrity": "sha512-HwLHA6ZrLSk7VHm5Bv3a8ljM6uU8+/670u2fKfMFwM4UQ42+yTFihwfFKLWQIcawBOlVCaUosr6o1xmeSquAqA==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.2.19", + "enhanced-resolve": "5.7.0", + "webpack-sources": "2.2.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "11.2.19", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.19.tgz", + "integrity": "sha512-kvS0QXDYDatLyf0NYv2sahPYD7kya4g5GpQAV1ddjjLmEVeZssHt+Xfk2tzrkzYzqRMiyspx3HPPrrOnMUAFhQ==", + "dev": true, + "requires": { + "ajv": "6.12.6", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.3", + "source-map": "0.7.3" + } + }, + "enhanced-resolve": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", + "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.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==", + "dev": true + }, + "@npmcli/git": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", + "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^6.1.1", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "lru-cache": "^6.0.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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "npm-package-arg": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", + "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" + } + }, + "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==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@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==", + "dev": true, + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@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==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "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" + } + } + } + }, + "@npmcli/node-gyp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz", + "integrity": "sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg==", + "dev": true + }, + "@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==", + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.5.tgz", + "integrity": "sha512-NQspusBCpTjNwNRFMtz2C5MxoxyzlbuJ4YEhxAKrIonTiirKDtatsZictx9RgamQIx6+QuHMNmPl0wQdoESs9A==", + "dev": true, + "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" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + } + } + }, + "@popperjs/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.0.0.tgz", + "integrity": "sha512-bN4670c4wr7RAOWTaf+h5KpC8al3h5fZSXqffakZrxZA01aKulM3rwIsU7qutrnYWw/nC1W06buOms/Rh+ZEDA==" + }, + "@schematics/angular": { + "version": "11.2.14", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-11.2.14.tgz", + "integrity": "sha512-nErn5BFYp4HB7mOkt23kF+dyM6zPxolejM8eXQ5vd/rdhcc6ROaMZ0EmeEAWkfqB3+vqaSDz/D2Nm/IjJlyW/Q==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.2.14", + "@angular-devkit/schematics": "11.2.14", + "jsonc-parser": "3.0.0" + } + }, + "@schematics/update": { + "version": "0.1102.14", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1102.14.tgz", + "integrity": "sha512-OsWuC0iyNjpST1+hVUUZAegXAFpEFpS5uKYSQF3jsbyw8XHx7oA5/HbEwyr2WkX2EdV1tKrDLz6BrD5b8W6EYw==", + "dev": true, + "requires": { + "@angular-devkit/core": "11.2.14", + "@angular-devkit/schematics": "11.2.14", + "@yarnpkg/lockfile": "1.1.0", + "ini": "2.0.0", + "npm-package-arg": "^8.0.0", + "pacote": "11.2.4", + "semver": "7.3.4", + "semver-intersect": "1.4.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "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==", + "dev": true + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "requires": { + "@types/node": "*" + } + }, + "@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "@types/core-js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.0.tgz", + "integrity": "sha512-qjkHL3wF0JMHMqgm/kmL8Pf8rIiqvueEiZ0g6NVTcBX1WN46GWDr+V5z+gsHUeL0n8TfAmXnYmF7ajsxmBp4PQ==", + "dev": true + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/hammerjs": { + "version": "2.0.35", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.35.tgz", + "integrity": "sha512-4mUIMSZ2U4UOWq1b+iV7XUTE4w+Kr3x+Zb/Qz5ROO6BTZLw2c8/ftjq0aRgluguLs4KRuBnrOy/s389HVn1/zA==", + "dev": true + }, + "@types/http-proxy": { + "version": "1.17.8", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", + "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "requires": { + "@types/node": "*" + } + }, + "@types/jasmine": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.11.tgz", + "integrity": "sha512-S6pvzQDvMZHrkBz2Mcn/8Du7cpr76PlRJBAoHnSDNbulULsH5dp0Gns+WRyNX5LHejz/ljxK4/vIHK/caHt6SQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/node": { + "version": "12.20.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.15.tgz", + "integrity": "sha512-F6S4Chv4JicJmyrwlDkxUdGNSplsQdGwp1A0AJloEVDirWdZOAiRHhovDlsFkKUrquUXhz1imJhXHsf59auyAg==" + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/protractor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/protractor/-/protractor-4.0.0.tgz", + "integrity": "sha1-EZFYRbONSD9wYNdOyOLu7kNXOZk=", + "dev": true, + "requires": { + "protractor": "*" + } + }, + "@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/retry": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + }, + "@types/selenium-webdriver": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz", + "integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==", + "dev": true + }, + "@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "requires": { + "@types/node": "*" + } + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/webpack-sources": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", + "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/ws": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.2.tgz", + "integrity": "sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw==", + "requires": { + "@types/node": "*" + } + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "dependencies": { + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "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==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "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" + } + }, + "ajv-errors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", + "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "requires": {} + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "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==" + } + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "requires": {} + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "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" + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "devOptional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "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==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "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" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", + "dev": true + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "devOptional": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autoprefixer": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.2.4.tgz", + "integrity": "sha512-DCCdUQiMD+P/as8m3XkeTUkUKuuRqLGcwD0nll7wevhqoJfMRpJlkFd1+MQh1pvupjiQuip42lc/VFvfUTMSKw==", + "dev": true, + "requires": { + "browserslist": "^4.16.1", + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "fraction.js": "^4.0.13", + "normalize-range": "^0.1.2", + "postcss-value-parser": "^4.1.0" + } + }, + "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.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } + }, + "babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "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" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.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 + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "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" + } + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "devOptional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "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" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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" + } + } + } + }, + "blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "requires": { + "bytes": "3.1.1", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" + }, + "dependencies": { + "bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + }, + "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" + } + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "bootstrap": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz", + "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==", + "requires": {} + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "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.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.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" + } + } + } + }, + "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": "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" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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" + } + }, + "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==" + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + } + }, + "browserstack": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz", + "integrity": "sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "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==" + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "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.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "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" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "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" + }, + "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" + } + }, + "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==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.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" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001239", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz", + "integrity": "sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==", + "dev": true + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "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==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "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" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "devOptional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "~5.1.2", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, + "optional": true + }, + "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==", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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=", + "bundled": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, + "optional": 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=", + "bundled": true, + "optional": 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=", + "bundled": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "bundled": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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==", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, + "optional": true, + "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" + } + }, + "glob": { + "version": "7.1.6", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "bundled": true, + "optional": 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" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "bundled": true, + "optional": true + }, + "ini": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.6.tgz", + "integrity": "sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg==", + "bundled": true, + "optional": true + }, + "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=", + "bundled": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "bundled": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, + "optional": true, + "requires": { + "minimist": "1.2.6" + }, + "dependencies": { + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "bundled": true, + "optional": true + } + } + }, + "ms": { + "version": "2.1.2", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "bundled": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "bundled": true, + "optional": true + }, + "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==", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "bundled": true, + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + } + } + }, + "nopt": { + "version": "4.0.1", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "bundled": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "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==", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "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=", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "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=", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.6", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, + "optional": true, + "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" + } + }, + "rimraf": { + "version": "2.7.1", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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==", + "bundled": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, + "optional": true + }, + "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==", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, + "optional": true, + "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=", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.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=", + "bundled": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "bundled": true, + "optional": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true + } + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-dependency-plugin": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz", + "integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", + "dev": true, + "requires": {} + }, + "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" + } + } + } + }, + "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-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "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" + } + }, + "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==" + }, + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "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==", + "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" + } + } + } + }, + "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==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.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=", + "dev": true + }, + "codelyzer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz", + "integrity": "sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==", + "dev": true, + "requires": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "dependencies": { + "@angular/compiler": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", + "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", + "dev": true, + "requires": {} + }, + "@angular/core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", + "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", + "dev": true, + "requires": {} + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "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" + } + }, + "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 + }, + "colord": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.0.1.tgz", + "integrity": "sha512-vm5YpaWamD0Ov6TSG0GGmUIwstrWcfKQV/h2CmbR7PbNu41+qdB5PW9lpzhjedrpm08uuYvcXi0Oel1RLZIJuA==", + "dev": true + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "compressible": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz", + "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==", + "requires": { + "mime-db": ">= 1.38.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "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" + } + } + } + }, + "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" + } + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.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" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "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=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + }, + "dependencies": { + "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==" + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-anything": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz", + "integrity": "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ==", + "dev": true, + "requires": { + "is-what": "^3.12.0" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-webpack-plugin": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.3.2.tgz", + "integrity": "sha512-MgJ1uouLIbDg4ST1GzqrGQyKoXY5iPqi6fghFqarijam7FQcBa/r6Rg0VkoIuzx75Xq8iAMghyOueMkWUQ5OaA==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "core-js": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.14.0.tgz", + "integrity": "sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==" + }, + "core-js-compat": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.1.tgz", + "integrity": "sha512-xGhzYMX6y7oEGQGAJmP2TmtBLvR4nZmRGEcFa3ubHOq5YEp51gGN9AovVa0AoujGZIq+Wm6dISiYyGNfdflYww==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "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=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "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=", + "dev": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "critters": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.12.tgz", + "integrity": "sha512-ujxKtKc/mWpjrOKeaACTaQ1aP0O31M0ZPWhfl85jZF1smPU4Ivb9va5Ox2poif4zVJQQo0LCFlzGtEZAsCAPcw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "css-select": "^4.1.3", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "postcss": "^8.3.7", + "pretty-bytes": "^5.3.0" + }, + "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.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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 + }, + "postcss": { + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", + "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", + "dev": true, + "requires": { + "nanoid": "^3.2.0", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "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" + } + } + } + }, + "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" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "css-color-names": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-1.0.1.tgz", + "integrity": "sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA==", + "dev": true + }, + "css-declaration-sorter": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.0.3.tgz", + "integrity": "sha512-52P95mvW1SMzuRZegvpluT6yEv0FqQusydKQPZsNN5Q7hh8EwQvN8E2nwuJ16BBvNN6LcoIZXu/Bk58DAhrrxw==", + "dev": true, + "requires": { + "timsort": "^0.3.0" + } + }, + "css-loader": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.0.1.tgz", + "integrity": "sha512-cXc2ti9V234cq7rJzFKhirb2L2iPy8ZjALeVJAozXYz9te3r4eqLSixNAbMDJSgJEQywqXzs8gonxaboeKqwiw==", + "dev": true, + "requires": { + "camelcase": "^6.2.0", + "cssesc": "^3.0.0", + "icss-utils": "^5.0.0", + "loader-utils": "^2.0.0", + "postcss": "^8.1.4", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + }, + "dependencies": { + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true + }, + "cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.2.tgz", + "integrity": "sha512-8JK3EnPsjQsULme9/e5M2hF564f/480hwsdcHvQ7ZtAIMfQ1O3SCfs+b8Mjf5KJxhYApyRshR2QSovEJi2K72Q==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "cssnano-preset-default": "^5.0.1", + "is-resolvable": "^1.1.0" + } + }, + "cssnano-preset-default": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.3.tgz", + "integrity": "sha512-qo9tX+t4yAAZ/yagVV3b+QBKeLklQbmgR3wI7mccrDcR+bEk9iHgZN1E7doX68y9ThznLya3RDmR+nc7l6/2WQ==", + "dev": true, + "requires": { + "css-declaration-sorter": "^6.0.3", + "cssnano-utils": "^2.0.1", + "postcss-calc": "^8.0.0", + "postcss-colormin": "^5.2.0", + "postcss-convert-values": "^5.0.1", + "postcss-discard-comments": "^5.0.1", + "postcss-discard-duplicates": "^5.0.1", + "postcss-discard-empty": "^5.0.1", + "postcss-discard-overridden": "^5.0.1", + "postcss-merge-longhand": "^5.0.2", + "postcss-merge-rules": "^5.0.2", + "postcss-minify-font-values": "^5.0.1", + "postcss-minify-gradients": "^5.0.1", + "postcss-minify-params": "^5.0.1", + "postcss-minify-selectors": "^5.1.0", + "postcss-normalize-charset": "^5.0.1", + "postcss-normalize-display-values": "^5.0.1", + "postcss-normalize-positions": "^5.0.1", + "postcss-normalize-repeat-style": "^5.0.1", + "postcss-normalize-string": "^5.0.1", + "postcss-normalize-timing-functions": "^5.0.1", + "postcss-normalize-unicode": "^5.0.1", + "postcss-normalize-url": "^5.0.2", + "postcss-normalize-whitespace": "^5.0.1", + "postcss-ordered-values": "^5.0.2", + "postcss-reduce-initial": "^5.0.1", + "postcss-reduce-transforms": "^5.0.1", + "postcss-svgo": "^5.0.2", + "postcss-unique-selectors": "^5.0.1" + } + }, + "cssnano-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz", + "integrity": "sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==", + "dev": true, + "requires": {} + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "damerau-levenshtein": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", + "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", + "dev": true + }, + "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" + } + }, + "date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": 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=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "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==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "requires": { + "execa": "^5.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==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "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" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "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==" + }, + "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==" + }, + "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" + } + } + } + }, + "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" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + } + } + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "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" + } + }, + "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" + } + } + } + }, + "del": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", + "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "dependencies": { + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, + "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" + } + } + } + }, + "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=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "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" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "requires": { + "buffer-indexof": "^1.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-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domino": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz", + "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==" + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "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==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "electron-to-chromium": { + "version": "1.3.757", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.757.tgz", + "integrity": "sha512-kP0ooyrvavDC+Y9UG6G/pUVxfRNM2VTJwtLQLvgsJeyf1V+7shMCb68Wj0/TETmfx8dWv9pToGkVT39udE87wQ==", + "dev": true + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + } + } + }, + "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==", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "optional": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", + "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "dev": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "ws": "~8.2.3" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "requires": { + "@socket.io/base64-arraybuffer": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + } + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true + }, + "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==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "requires": { + "prr": "~1.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "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=", + "dev": true + }, + "eslint": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz", + "integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.2.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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" + } + }, + "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 + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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 + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "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 + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "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 + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "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" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", + "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "dev": true, + "requires": { + "acorn": "^8.7.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "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==", + "dev": true + }, + "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==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "eventsource": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", + "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "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" + }, + "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" + } + } + } + }, + "express": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "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" + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + }, + "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==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + } + } + }, + "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" + }, + "dependencies": { + "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==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "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" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "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-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" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "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==", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "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-xml-parser": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz", + "integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==" + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "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" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, + "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" + } + }, + "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" + } + }, + "file-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz", + "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==", + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "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" + }, + "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" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.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" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + } + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "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, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "dependencies": { + "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 + } + } + }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" + }, + "font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "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.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fraction.js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz", + "integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==", + "dev": true + }, + "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" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "front-matter": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-2.1.2.tgz", + "integrity": "sha1-91mDufL0E75ljJPf172M5AePXNs=", + "dev": true, + "requires": { + "js-yaml": "^3.4.6" + } + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.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==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "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==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "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=", + "dev": true, + "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" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "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 + }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "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", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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" + } + }, + "glob-parent": { + "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": "^4.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "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 + } + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "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" + }, + "dependencies": { + "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==" + } + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "gonzales-pe-sl": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/gonzales-pe-sl/-/gonzales-pe-sl-4.2.3.tgz", + "integrity": "sha1-aoaLw4BkXxQf7rBCxvl/zHG1n+Y=", + "dev": true, + "requires": { + "minimist": "1.2.5" + } + }, + "got": { + "version": "6.7.1", + "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "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" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==" + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "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=", + "dev": true, + "requires": { + "ansi-regex": "^2.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 + }, + "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 + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "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" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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" + } + }, + "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==" + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==" + }, + "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==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-parser-js": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", + "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + } + } + }, + "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==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "http-proxy-middleware": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz", + "integrity": "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==", + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "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==", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "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==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "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==" + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "ignore-walk": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", + "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "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, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "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 + } + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.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==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.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==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "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==" + }, + "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", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.6.tgz", + "integrity": "sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg==", + "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-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.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": "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 + }, + "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.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" + } + }, + "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" + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "dependencies": { + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "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==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, + "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=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "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.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "devOptional": true, + "requires": { + "binary-extensions": "^1.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-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + }, + "dependencies": { + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + } + } + }, + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "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=", + "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-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-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "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=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + } + }, + "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==" + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", + "dev": true + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "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" + } + } + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + }, + "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==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.1.tgz", + "integrity": "sha512-h2CGs+yPUyvkgTJQS9cJzo9lYK06WgRiXUqBBHtglSzVKAuH4/oWsqk7LGfbSa1hGk9QcZ0SyQtVggvBA8LZXA==", + "requires": { + "fast-xml-parser": "^3.19.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, + "is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "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==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "requires": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "dependencies": { + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + } + } + }, + "jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz", + "integrity": "sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g==", + "dev": true, + "requires": { + "colors": "1.4.0" + } + }, + "jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "jquery": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.0.tgz", + "integrity": "sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ==" + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "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=", + "optional": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "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-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==", + "dev": true + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "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-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-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": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "jszip": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "karma": { + "version": "6.3.16", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.16.tgz", + "integrity": "sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==", + "dev": true, + "requires": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "colors": "1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "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 + }, + "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" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "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": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.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 + }, + "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": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, + "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, + "requires": { + "binary-extensions": "^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==", + "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 + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "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" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "requires": { + "which": "^1.2.1" + } + }, + "karma-cli": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma-cli/-/karma-cli-2.0.0.tgz", + "integrity": "sha512-1Kb28UILg1ZsfqQmeELbPzuEb5C6GZJfVIk0qOr8LNYQuYWmAaqP16WpbpKEjhejDrDYyYOwwJXSZO6u7q5Pvw==", + "dev": true, + "requires": { + "resolve": "^1.3.3" + } + }, + "karma-jasmine": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.1.tgz", + "integrity": "sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==", + "dev": true, + "requires": { + "jasmine-core": "^3.6.0" + }, + "dependencies": { + "jasmine-core": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.7.1.tgz", + "integrity": "sha512-DH3oYDS/AUvvr22+xUBW62m1Xoy7tUlY1tsxKEJvl5JeJ7q8zd1K5bUwiOxdH+erj6l2vAMM3hV25Xs9/WrmuQ==", + "dev": true + } + } + }, + "karma-jasmine-html-reporter": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", + "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", + "dev": true, + "requires": {} + }, + "karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "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==" + }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz", + "integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==", + "dev": true + }, + "known-css-properties": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.3.0.tgz", + "integrity": "sha512-QMQcnKAiQccfQTqtBh/qwquGZ2XK/DXND1jrcN9M8gMMy99Gwla7GQjndVUsEqIaRyP6bsFRuhwRj5poafBGJQ==", + "dev": true + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "^4.0.0" + } + }, + "less": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", + "integrity": "sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw==", + "dev": true, + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^2.5.2", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "less-loader": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-7.3.0.tgz", + "integrity": "sha512-Mi8915g7NMaLlgi77mgTTQvK022xKRQBIVDSyfl3ErTuBhmZBQab0mjeJjNNqGbdR+qrfTleKXqbGI4uEFavxg==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "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" + } + }, + "license-webpack-plugin": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.11.tgz", + "integrity": "sha512-0iVGoX5vx0WDy8dmwTTpOOMYiGqILyUbDeVMFH52AjgBlS58lHwOlFMSoqg5nY8Kxl6+FRKyUZY/UdlQaOyqDw==", + "dev": true, + "requires": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "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=", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==" + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "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, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha1-+CbJtOKoUR2E46yinbBeGk87cqk=", + "dev": true + }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "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" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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==" + }, + "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==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, + "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==", + "dev": true, + "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" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "requires": { + "fs-monkey": "1.0.3" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "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==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "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" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "requires": { + "mime-db": "1.51.0" + } + }, + "mini-css-extract-plugin": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-1.3.5.tgz", + "integrity": "sha512-tvmzcwqJJXau4OQE5vT72pRT18o2zF+tQJp8CWchqvfQnTlflkzS+dANYcRdyPRWUWRkfmeNTKltx0NZI/b5dQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "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" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "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==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz", + "integrity": "sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ==", + "dev": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "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==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "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" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "optional": true + }, + "nanoid": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "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" + } + }, + "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 + }, + "needle": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", + "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.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, + "optional": true + } + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "ngx-toastr": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-13.2.1.tgz", + "integrity": "sha512-UAzp7/xWK9IXA2LsOmhpaaIGCqscvJokoQpBNpAMrjEkDeSlFf8PWQAuQY795KW0mJb3qF9UG/s23nsXfMYKmg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "dev": true, + "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" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "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" + } + }, + "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" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "nodemon": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.4.tgz", + "integrity": "sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^2.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.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 + }, + "pstree.remy": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz", + "integrity": "sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A==", + "dev": true + }, + "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" + } + } + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "devOptional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "normalize.css": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz", + "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A==" + }, + "npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "semver": "^7.1.1" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "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==", + "dev": true + }, + "npm-package-arg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.0.tgz", + "integrity": "sha512-/ep6QDxBkm9HvOhOg0heitSd7JHA1U7y1qhhlRlteYYAi9Pdb/ZV7FW5aHpkrpM8+P+4p/jjR8zCyKPBMBjSig==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "semver": "^7.0.0", + "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "npm-packlist": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.2.2.tgz", + "integrity": "sha512-Jt01acDvJRhJGthnUJVF/w6gumWOZxO7IkpY/lsX9//zqQgnF7OJaxgQXcerd4uQOLu7W5bkb4mChL9mdfm+Zg==", + "dev": true, + "requires": { + "glob": "^7.1.6", + "ignore-walk": "^3.0.3", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + } + } + }, + "npm-pick-manifest": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.0.tgz", + "integrity": "sha512-ygs4k6f54ZxJXrzT0x34NybRlLeZ4+6nECAIbr2i0foTnijtS1TJiyzpqtuUAJOps/hO0tNDr8fRV5g+BtRlTw==", + "dev": true, + "requires": { + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.0.0", + "semver": "^7.0.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "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==", + "dev": true, + "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" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "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=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-watch": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/npm-watch/-/npm-watch-0.5.0.tgz", + "integrity": "sha512-Rww9iNlmsVhcpUTDoKfUlbfmEtTZ3T3gUZBW/VjuL4ct/nwV0XlwBDOxR0ECJ/cLF8PF1wPVa/IrinI6K5ECQQ==", + "dev": true, + "requires": { + "nodemon": "^1.18.7", + "through2": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "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=", + "dev": true + }, + "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-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "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" + } + } + } + }, + "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-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "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": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^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==" + } + } + }, + "open": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.0.tgz", + "integrity": "sha512-PGoBCX/lclIWlpS/R2PQuIR4NJoXh6X5AwVzE7WXnWRGvHg7+4TBCgsujUgiPpm0K1y4qvQeWnCWVTpTKZBtvA==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "dependencies": { + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + } + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "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": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "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" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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.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" + } + } + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "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=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "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", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.1.tgz", + "integrity": "sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==", + "requires": { + "@types/retry": "^0.12.0", + "retry": "^0.13.1" + }, + "dependencies": { + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + } + } + }, + "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==" + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, + "pacote": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.2.4.tgz", + "integrity": "sha512-GfTeVQGJ6WyBQbQD4t3ocHbyOmTQLmWjkCKSZPmKiGFKYKNUaM5U2gbLzUW8WG1XmS9yQFnsTFA0k3o1+q4klQ==", + "dev": true, + "requires": { + "@npmcli/git": "^2.0.1", + "@npmcli/installed-package-contents": "^1.0.5", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.3.0", + "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": "^1.1.1", + "read-package-json-fast": "^1.1.3", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.1.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "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" + } + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "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": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "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==", + "dev": true, + "requires": { + "@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" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-html-rewriting-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", + "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "dev": true, + "requires": { + "parse5": "^6.0.1", + "parse5-sax-parser": "^6.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + } + }, + "parse5-sax-parser": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", + "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "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-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "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=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "dev": true, + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "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=" + }, + "postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-calc": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.0.0.tgz", + "integrity": "sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "postcss-colormin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.0.tgz", + "integrity": "sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-convert-values": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz", + "integrity": "sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-discard-comments": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz", + "integrity": "sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg==", + "dev": true, + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz", + "integrity": "sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA==", + "dev": true, + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz", + "integrity": "sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw==", + "dev": true, + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz", + "integrity": "sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q==", + "dev": true, + "requires": {} + }, + "postcss-import": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.0.0.tgz", + "integrity": "sha512-gFDDzXhqr9ELmnLHgCC3TbGfA6Dm/YMb/UN8/f7Uuq4fL7VTk2vOIj6hwINEwbokEmp123bLD7a5m+E+KIetRg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-loader": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.2.0.tgz", + "integrity": "sha512-mqgScxHqbiz1yxbnNcPdKYo/6aVt+XExURmEbQlviFVWogDbM4AJ0A/B+ZBpYsJrTRxKw7HyRazg9x0Q9SWwLA==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "postcss-merge-longhand": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz", + "integrity": "sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw==", + "dev": true, + "requires": { + "css-color-names": "^1.0.1", + "postcss-value-parser": "^4.1.0", + "stylehacks": "^5.0.1" + } + }, + "postcss-merge-rules": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz", + "integrity": "sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^2.0.1", + "postcss-selector-parser": "^6.0.5", + "vendors": "^1.0.3" + } + }, + "postcss-minify-font-values": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz", + "integrity": "sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-minify-gradients": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.1.tgz", + "integrity": "sha512-odOwBFAIn2wIv+XYRpoN2hUV3pPQlgbJ10XeXPq8UY2N+9ZG42xu45lTn/g9zZ+d70NKSQD6EOi6UiCMu3FN7g==", + "dev": true, + "requires": { + "cssnano-utils": "^2.0.1", + "is-color-stop": "^1.1.0", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-minify-params": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz", + "integrity": "sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.2", + "browserslist": "^4.16.0", + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz", + "integrity": "sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.2", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-normalize-charset": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz", + "integrity": "sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg==", + "dev": true, + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz", + "integrity": "sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ==", + "dev": true, + "requires": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-positions": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz", + "integrity": "sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz", + "integrity": "sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w==", + "dev": true, + "requires": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-string": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz", + "integrity": "sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz", + "integrity": "sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q==", + "dev": true, + "requires": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz", + "integrity": "sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA==", + "dev": true, + "requires": { + "browserslist": "^4.16.0", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-url": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz", + "integrity": "sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ==", + "dev": true, + "requires": { + "is-absolute-url": "^3.0.3", + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz", + "integrity": "sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-ordered-values": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz", + "integrity": "sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ==", + "dev": true, + "requires": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-reduce-initial": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz", + "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==", + "dev": true, + "requires": { + "browserslist": "^4.16.0", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz", + "integrity": "sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA==", + "dev": true, + "requires": { + "cssnano-utils": "^2.0.1", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", + "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.2.tgz", + "integrity": "sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.1.0", + "svgo": "^2.3.0" + } + }, + "postcss-unique-selectors": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz", + "integrity": "sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.2", + "postcss-selector-parser": "^6.0.5", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "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 + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "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==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + }, + "dependencies": { + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + } + } + }, + "protractor": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "dev": true, + "requires": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "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" + } + }, + "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 + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^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==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "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" + } + }, + "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" + } + }, + "webdriver-manager": { + "version": "12.1.8", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.8.tgz", + "integrity": "sha512-qJR36SXG2VwKugPcdwhaqcLQOD7r8P2Xiv9sfNbfZrKBnX243iAkOueX1yAmeNgIKhJ3YAT/F2gq6IiEZzahsg==", + "dev": true, + "requires": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + } + }, + "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, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "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, + "requires": { + "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" + } + }, + "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": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "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" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "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=" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "requires": { + "bytes": "3.1.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + } + } + }, + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "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=", + "dev": true + } + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-package-json-fast": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-1.2.2.tgz", + "integrity": "sha512-39DbPJjkltEzfXJXB6D8/Ir3GFOU2YbSKa2HaB/Y3nKrc/zY+0XrALpID6/13ezWyzqvOHrBbR4t4cjQuTdBVQ==", + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "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" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "devOptional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "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" + } + }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", + "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "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=", + "devOptional": true + }, + "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=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "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.0", + "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.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "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-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==" + }, + "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 + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "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=" + }, + "resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "dependencies": { + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "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==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rollup": { + "version": "2.38.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.4.tgz", + "integrity": "sha512-B0LcJhjiwKkTl79aGVF/u5KdzsH8IylVfV56Ut6c9ouWLJcUK17T83aZBetNYSnZtXf2OHD4+2PbmRW+Fp5ulg==", + "dev": true, + "requires": { + "fsevents": "~2.3.1" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "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==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "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" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "rxjs-compat": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs-compat/-/rxjs-compat-6.6.7.tgz", + "integrity": "sha512-szN4fK+TqBPOFBcBcsR0g2cmTTUF/vaFEOZNuSdfU8/pGFnNmmn2u8SystYXG1QMrjOPBc6XTKHMVfENDf6hHw==" + }, + "rxjs-tslint": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/rxjs-tslint/-/rxjs-tslint-0.1.8.tgz", + "integrity": "sha512-4MNcco1pugjNyjkUkvJ9ngJSMCuwmyc1g6EkEYzlTK0PrZxm8xVaBeBz5aPLE3AzldQbYkOErOVAayUlzQkjAg==", + "dev": true, + "requires": { + "chalk": "^2.4.0", + "tslint": "^5.9.1", + "tsutils": "^2.25.0", + "typescript": ">=2.8.3", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "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" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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" + } + }, + "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" + } + }, + "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 + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "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.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" + } + }, + "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" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + } + }, + "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, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "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" + } + }, + "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" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "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, + "requires": { + "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" + } + }, + "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": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "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==" + }, + "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" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass": { + "version": "1.32.6", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.32.6.tgz", + "integrity": "sha512-1bcDHDcSqeFtMr0JXI3xc/CXX6c4p0wHHivJdru8W7waM7a1WjKMm4m/Z5sY7CbVw4Whi2Chpcw6DFfSWwGLzQ==", + "dev": true, + "requires": { + "chokidar": ">=2.0.0 <4.0.0" + } + }, + "sass-lint": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sass-lint/-/sass-lint-1.13.1.tgz", + "integrity": "sha512-DSyah8/MyjzW2BWYmQWekYEKir44BpLqrCFsgs9iaWiVTcwZfwXHF586hh3D1n+/9ihUNMfd8iHAyb9KkGgs7Q==", + "dev": true, + "requires": { + "commander": "^2.8.1", + "eslint": "8.10.0", + "front-matter": "2.1.2", + "fs-extra": "^3.0.1", + "glob": "^7.0.0", + "globule": "^1.0.0", + "gonzales-pe-sl": "^4.2.3", + "js-yaml": "^3.5.4", + "known-css-properties": "^0.3.0", + "lodash.capitalize": "^4.1.0", + "lodash.kebabcase": "^4.0.0", + "merge": "2.1.1", + "path-is-absolute": "^1.0.0", + "util": "^0.10.3" + } + }, + "sass-loader": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.1.1.tgz", + "integrity": "sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + }, + "selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "requires": { + "node-forge": "^1.3.1" + }, + "dependencies": { + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + } + }, + "semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "requires": { + "semver": "^5.0.0" + } + }, + "send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.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" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + } + } + }, + "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": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "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" + } + } + } + }, + "serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "dependencies": { + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + } + } + }, + "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-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "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 + }, + "shiki": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", + "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "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==", + "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==", + "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" + } + } + } + }, + "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==", + "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" + } + } + } + }, + "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" + }, + "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" + } + } + } + }, + "socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "dependencies": { + "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==", + "dev": true + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + } + } + }, + "sockjs-client": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.6.0.tgz", + "integrity": "sha512-qVHJlyfdHFht3eBFZdKEXKTlb7I4IV41xnVNo8yUKA1UHcPJwgW2SvTq9LhnjjCywSkSK7c/e4nghU0GOoMCRQ==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "eventsource": "^1.1.0", + "faye-websocket": "^0.11.4", + "inherits": "^2.0.4", + "url-parse": "^1.5.10" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "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 + } + } + }, + "socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-loader": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-1.1.3.tgz", + "integrity": "sha512-6YHeF+XzDOrT/ycFJNI53cgEsp/tHTMl37hi7uVyqFAlTXW109JazaQCkbc+jjoL2637qkH1amLi+JzrIpt5lA==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.2", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "source-map": "^0.6.1", + "whatwg-mimetype": "^2.3.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "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=" + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "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==" + }, + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "speed-measure-webpack-plugin": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.4.2.tgz", + "integrity": "sha512-AtVzD0bnIy2/B0fWqJpJgmhcrfWFhBlduzSo0uwplr/QvB33ZNZj2NEth3NONgdnZJqicK0W0mSxnLSbsVCDbw==", + "dev": true, + "requires": { + "chalk": "^4.1.0" + }, + "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.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "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" + } + } + } + }, + "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" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "sshpk": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "requires": { + "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" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "requires": { + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "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" + } + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + }, + "streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.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" + } + }, + "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 + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "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" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "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=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "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==" + }, + "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 + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "stylehacks": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz", + "integrity": "sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA==", + "dev": true, + "requires": { + "browserslist": "^4.16.0", + "postcss-selector-parser": "^6.0.4" + } + }, + "stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "stylus-loader": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-4.3.3.tgz", + "integrity": "sha512-PpWB5PnCXUzW4WMYhCvNzAHJBjIBPMXwsdfkkKuA9W7k8OQFMl/19/AQvaWsxz2IptxUlCseyJ6TY/eEKJ4+UQ==", + "dev": true, + "requires": { + "fast-glob": "^3.2.4", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + } + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "tar": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.9.tgz", + "integrity": "sha512-XjLaMNl76o07zqZC/aW4lwegdY07baOH1T8w3AEfrHAdyg/oYO4ctjzEBq9Gy9fEP9oHqLIgvx6zuGDGe+bc8Q==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, + "terser": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", + "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "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" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.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" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==" + }, + "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=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "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=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + } + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "ts-helpers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ts-helpers/-/ts-helpers-1.1.2.tgz", + "integrity": "sha1-/Gm+nx87rtAfsaDvjUz+dIgU2DU=", + "dev": true, + "requires": {} + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + } + }, + "ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.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" + } + }, + "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" + } + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "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" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "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, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "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 + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedoc": { + "version": "0.22.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.11.tgz", + "integrity": "sha512-pVr3hh6dkS3lPPaZz1fNpvcrqLdtEvXmXayN55czlamSgvEjh+57GUqfhAI1Xsuu/hNHUT1KNSx8LH2wBP/7SA==", + "dev": true, + "requires": { + "glob": "^7.2.0", + "lunr": "^2.3.9", + "marked": "^4.0.10", + "minimatch": "^3.0.4", + "shiki": "^0.10.0" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + } + } + }, + "typescript": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.8.tgz", + "integrity": "sha512-oz1765PN+imfz1MlZzSZPtC/tqcwsCyIYA8L47EkRnRW97ztRk83SzMiWLrnChC0vqoYxSU1fcFUDA5gV/ZiPg==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true + }, + "uglify-js": { + "version": "3.13.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.9.tgz", + "integrity": "sha512-wZbyTQ1w6Y7fHdt8sJnHfSIuWeDgk6B5rCb4E/AM6QNNPbOMIZph21PW5dRB3h7Df0GszN+t7RuUH6sWK5bF0g==", + "dev": true, + "optional": true + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "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==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.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" + } + }, + "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==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + } + } + } + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "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" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "universal-analytics": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.23.tgz", + "integrity": "sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "request": "^2.88.2", + "uuid": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "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 + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "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" + } + }, + "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==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "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=" + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "devOptional": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^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" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "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==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "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==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "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-loader": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.1.tgz", + "integrity": "sha512-vugEeXjyYFBCUOpX+ZuaunbK3QXMKaQ3zUnRfIpRBlGkY7QizCnzyyn2ASfcxsvyU3ef+CJppVywnl3Kgf13Gg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + } + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + }, + "dependencies": { + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + } + } + }, + "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=", + "dev": true, + "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": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "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 + }, + "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=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "vscode-oniguruma": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.1.tgz", + "integrity": "sha512-vc4WhSIaVpgJ0jJIejjYxPvURJavX6QG41vu0mGhqywMkQqulezEqEQ3cO3gc8GvcOpX6ycmKGqRoROEMBNXTQ==", + "dev": true + }, + "vscode-textmate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", + "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "dev": true + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "optional": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "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==", + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "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==", + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "optional": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "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==", + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, + "webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "requires": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-dev-server": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz", + "integrity": "sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==", + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.2.2", + "ansi-html-community": "^0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "default-gateway": "^6.0.3", + "del": "^6.0.0", + "express": "^4.17.1", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.0", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "schema-utils": "^4.0.0", + "selfsigned": "^2.0.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "strip-ansi": "^7.0.0", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "dependencies": { + "ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "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" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + }, + "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" + } + }, + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + }, + "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==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.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==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + }, + "selfsigned": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.0.tgz", + "integrity": "sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ==", + "requires": { + "node-forge": "^1.3.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "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==", + "requires": { + "is-number": "^7.0.0" + } + }, + "webpack-dev-middleware": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz", + "integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==", + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.1", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "requires": {} + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-subresource-integrity": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.2.tgz", + "integrity": "sha512-GBWYBoyalbo5YClwWop9qe6Zclp8CIXYGIz12OPclJhIrSplDxs1Ls1JDMH8xBPPrg1T6ISaTW9Y6zOrwEiAzw==", + "dev": true, + "requires": { + "webpack-sources": "^1.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "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 + }, + "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" + } + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "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 + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "requires": { + "errno": "~0.1.7" + } + }, + "worker-plugin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.0.tgz", + "integrity": "sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ==", + "dev": true, + "requires": { + "loader-utils": "^1.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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "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" + } + }, + "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" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "xhr2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz", + "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "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==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "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 + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.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==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "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" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "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" + } + } + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "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==", + "dev": true + }, + "zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" + } + } +} diff --git a/src/Web/WebSPA/package.json b/src/Web/WebSPA/Client/package.json similarity index 64% rename from src/Web/WebSPA/package.json rename to src/Web/WebSPA/Client/package.json index d1f140331..f6b0746d5 100644 --- a/src/Web/WebSPA/package.json +++ b/src/Web/WebSPA/Client/package.json @@ -28,70 +28,71 @@ }, "dependencies": { "@angular-devkit/schematics": "^11.0.4", - "@angular/animations": "10.2.3", - "@angular/common": "10.2.3", - "@angular/compiler": "10.2.3", - "@angular/core": "10.2.3", - "@angular/forms": "10.2.3", - "@angular/platform-browser": "10.2.3", - "@angular/platform-browser-dynamic": "10.2.3", - "@angular/platform-server": "10.2.3", - "@angular/router": "10.2.3", + "@angular/animations": "11.2.14", + "@angular/common": "11.2.14", + "@angular/compiler": "11.2.14", + "@angular/core": "11.2.14", + "@angular/forms": "11.2.14", + "@angular/platform-browser": "11.2.14", + "@angular/platform-browser-dynamic": "11.2.14", + "@angular/platform-server": "11.2.14", + "@angular/router": "11.2.14", "@microsoft/signalr": "3.0.1", "@ng-bootstrap/ng-bootstrap": "^8.0.0", "@popperjs/core": "2.0.0", "acorn": "^6.4.1", "acorn-dynamic-import": "4.0.0", "bootstrap": "4.4.1", - "core-js": "^3.0.0", + "core-js": "^3.14.0", "file-loader": "2.0.0", "font-awesome": "4.7.0", - "isomorphic-fetch": "2.2.1", + "is-svg": ">=4.2.2", + "isomorphic-fetch": "3.0.0", "jquery": "3.5.0", "ngx-toastr": "^13.2.0", "normalize.css": "8.0.0", "popper.js": "1.16.1", "rxjs": "^6.5.2", "rxjs-compat": "^6.5.2", + "ssri": ">=8.0.1", "tslib": "^2.0.0", - "typedoc": "^0.19.2", - "webpack-dev-server": "3.1.14", + "typedoc": "0.22.11", + "webpack-dev-server": "4.7.4", "zone.js": "~0.10.2" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.1002.0", - "@angular/cli": "10.2.0", - "@angular/compiler-cli": "10.2.3", - "@angular/language-service": "10.2.3", + "@angular-devkit/build-angular": "~0.1102.14", + "@angular/cli": "11.2.14", + "@angular/compiler-cli": "11.2.14", + "@angular/language-service": "11.2.14", "@types/core-js": "2.5.0", "@types/hammerjs": "2.0.35", - "@types/jasmine": "^3.5.10", + "@types/jasmine": "~3.6.0", "@types/node": "^12.11.1", "@types/protractor": "4.0.0", "@types/selenium-webdriver": "3.0.10", - "codelyzer": "^5.1.2", - "eslint": "^6.8.0", - "handlebars": "^4.7.6", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "eslint": "8.10.0", + "handlebars": "^4.7.7", + "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", - "karma": "~5.0.0", + "karma": "~6.3.16", "karma-chrome-launcher": "~3.1.0", "karma-cli": "^2.0.0", "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.5.0", - "lodash": "^4.17.19", - "merge": "1.2.1", + "lodash": "^4.17.21", + "merge": "2.1.1", "npm-watch": "0.5.0", "protractor": "~7.0.0", - "rxjs-tslint": "^0.1.7", - "sass-lint": "1.12.1", + "rxjs-tslint": "^0.1.8", + "sass-lint": "^1.13.1", "ts-helpers": "1.1.2", "ts-node": "~7.0.1", "tslint": "~6.1.0", - "typedoc": "^0.19.2", - "typescript": "4.0.5", + "typedoc": "0.22.11", + "typescript": "4.0.8", "url-loader": "1.1.1", "webpack": "^4.42.1" - }, - "peerDependencies": {} + } } diff --git a/src/Web/WebSPA/Client/assets/.gitkeep b/src/Web/WebSPA/Client/src/assets/.gitkeep similarity index 100% rename from src/Web/WebSPA/Client/assets/.gitkeep rename to src/Web/WebSPA/Client/src/assets/.gitkeep diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.eot b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.eot new file mode 100644 index 000000000..1d59b4860 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.eot differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.svg b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.svg new file mode 100644 index 000000000..ca947a830 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.svg @@ -0,0 +1,3184 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.ttf b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.ttf new file mode 100644 index 000000000..b36d676e1 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.ttf differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.woff b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.woff new file mode 100644 index 000000000..3235009f1 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.woff differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.woff2 b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.woff2 new file mode 100644 index 000000000..b9363b1d2 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Bold.woff2 differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.eot b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.eot new file mode 100644 index 000000000..ea55b5d88 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.eot differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.svg b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.svg new file mode 100644 index 000000000..822eec9d3 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.svg @@ -0,0 +1,2860 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.ttf b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.ttf new file mode 100644 index 000000000..c5f704498 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.ttf differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.woff b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.woff new file mode 100644 index 000000000..843da1430 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.woff differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.woff2 b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.woff2 new file mode 100644 index 000000000..42cfba52c Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-ExtraLight.woff2 differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.eot b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.eot new file mode 100644 index 000000000..d95eec454 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.eot differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.svg b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.svg new file mode 100644 index 000000000..50f1d7539 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.svg @@ -0,0 +1,2902 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.ttf b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.ttf new file mode 100644 index 000000000..d70424cd8 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.ttf differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.woff b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.woff new file mode 100644 index 000000000..3c448fca4 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.woff differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.woff2 b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.woff2 new file mode 100644 index 000000000..6e9b9a97a Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Light.woff2 differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.eot b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.eot new file mode 100644 index 000000000..e8a3c5094 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.eot differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.svg b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.svg new file mode 100644 index 000000000..fa9da77bf --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.svg @@ -0,0 +1,3232 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.ttf b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.ttf new file mode 100644 index 000000000..d0ab912cf Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.ttf differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.woff b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.woff new file mode 100644 index 000000000..6af5288a6 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.woff differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.woff2 b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.woff2 new file mode 100644 index 000000000..b7514b872 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Medium.woff2 differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.eot b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.eot new file mode 100644 index 000000000..10c4df61d Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.eot differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.svg b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.svg new file mode 100644 index 000000000..a28247311 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.svg @@ -0,0 +1,2720 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.ttf b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.ttf new file mode 100644 index 000000000..2492c44a2 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.ttf differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.woff b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.woff new file mode 100644 index 000000000..1aff4945d Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.woff differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.woff2 b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.woff2 new file mode 100644 index 000000000..626d517ec Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-Regular.woff2 differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.eot b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.eot new file mode 100644 index 000000000..bd08ba217 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.eot differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.svg b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.svg new file mode 100644 index 000000000..2114fe93e --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.svg @@ -0,0 +1,3197 @@ + + + + +Created by FontForge 20170731 at Tue Apr 30 17:14:28 2019 + By Aleksey,,, +Copyright 2016 The Oswald Project Authors (https://github.com/googlefonts/OswaldFont) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.ttf b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.ttf new file mode 100644 index 000000000..b1b50d68f Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.ttf differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.woff b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.woff new file mode 100644 index 000000000..305eb488a Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.woff differ diff --git a/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.woff2 b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.woff2 new file mode 100644 index 000000000..e31be5404 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/fonts/Oswald-SemiBold.woff2 differ diff --git a/src/Web/WebSPA/Client/src/assets/images/add.svg b/src/Web/WebSPA/Client/src/assets/images/add.svg new file mode 100644 index 000000000..2ac535502 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/add.svg @@ -0,0 +1,9 @@ + + + + icons/24/Add to cart + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/assets/images/arrow-right.svg b/src/Web/WebSPA/Client/src/assets/images/arrow-right.svg similarity index 100% rename from src/Web/WebSPA/Client/assets/images/arrow-right.svg rename to src/Web/WebSPA/Client/src/assets/images/arrow-right.svg diff --git a/src/Web/WebSPA/Client/src/assets/images/cart.svg b/src/Web/WebSPA/Client/src/assets/images/cart.svg new file mode 100644 index 000000000..221fbaae9 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/cart.svg @@ -0,0 +1,9 @@ + + + + icons/24/Cart + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/delete.svg b/src/Web/WebSPA/Client/src/assets/images/delete.svg new file mode 100644 index 000000000..169d0fceb --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/delete.svg @@ -0,0 +1,9 @@ + + + + icons/24/X + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/header.jpg b/src/Web/WebSPA/Client/src/assets/images/header.jpg new file mode 100644 index 000000000..c8aa750c8 Binary files /dev/null and b/src/Web/WebSPA/Client/src/assets/images/header.jpg differ diff --git a/src/Web/WebSPA/Client/src/assets/images/logo.svg b/src/Web/WebSPA/Client/src/assets/images/logo.svg new file mode 100644 index 000000000..1e736705c --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/logo.svg @@ -0,0 +1,14 @@ + + + + Group 5 + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/logo_color.svg b/src/Web/WebSPA/Client/src/assets/images/logo_color.svg new file mode 100644 index 000000000..e56235262 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/logo_color.svg @@ -0,0 +1,14 @@ + + + + Group 5 + Created with Sketch. + + + + + + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/minus.svg b/src/Web/WebSPA/Client/src/assets/images/minus.svg new file mode 100644 index 000000000..b02922539 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/minus.svg @@ -0,0 +1,9 @@ + + + + icons/24/Minus + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/plus.svg b/src/Web/WebSPA/Client/src/assets/images/plus.svg new file mode 100644 index 000000000..a733ac4b2 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/plus.svg @@ -0,0 +1,9 @@ + + + + icons/24/Plus + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/refresh.svg b/src/Web/WebSPA/Client/src/assets/images/refresh.svg new file mode 100644 index 000000000..25b2851fa --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/refresh.svg @@ -0,0 +1,9 @@ + + + + icons/24/Refresh + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/assets/images/user.svg b/src/Web/WebSPA/Client/src/assets/images/user.svg new file mode 100644 index 000000000..7553487a6 --- /dev/null +++ b/src/Web/WebSPA/Client/src/assets/images/user.svg @@ -0,0 +1,9 @@ + + + + icons/24/User + Created with Sketch. + + + + \ No newline at end of file diff --git a/src/Web/WebSPA/Client/environments/environment.prod.ts b/src/Web/WebSPA/Client/src/environments/environment.prod.ts similarity index 100% rename from src/Web/WebSPA/Client/environments/environment.prod.ts rename to src/Web/WebSPA/Client/src/environments/environment.prod.ts diff --git a/src/Web/WebSPA/Client/environments/environment.ts b/src/Web/WebSPA/Client/src/environments/environment.ts similarity index 100% rename from src/Web/WebSPA/Client/environments/environment.ts rename to src/Web/WebSPA/Client/src/environments/environment.ts diff --git a/src/Web/WebSPA/Client/src/favicon.ico b/src/Web/WebSPA/Client/src/favicon.ico new file mode 100644 index 000000000..a8570bc42 Binary files /dev/null and b/src/Web/WebSPA/Client/src/favicon.ico differ diff --git a/src/Web/WebSPA/Client/guid.ts b/src/Web/WebSPA/Client/src/guid.ts similarity index 100% rename from src/Web/WebSPA/Client/guid.ts rename to src/Web/WebSPA/Client/src/guid.ts diff --git a/src/Web/WebSPA/Client/index.html b/src/Web/WebSPA/Client/src/index.html similarity index 85% rename from src/Web/WebSPA/Client/index.html rename to src/Web/WebSPA/Client/src/index.html index 5d9432f70..013d9316d 100644 --- a/src/Web/WebSPA/Client/index.html +++ b/src/Web/WebSPA/Client/src/index.html @@ -1,8 +1,8 @@ - + - eShopConContainers.WebSPA + eShopOnContainers - SPA diff --git a/src/Web/WebSPA/Client/main.ts b/src/Web/WebSPA/Client/src/main.ts similarity index 100% rename from src/Web/WebSPA/Client/main.ts rename to src/Web/WebSPA/Client/src/main.ts diff --git a/src/Web/WebSPA/Client/src/modules/app.component.html b/src/Web/WebSPA/Client/src/modules/app.component.html new file mode 100644 index 000000000..fd5bde633 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/app.component.html @@ -0,0 +1,40 @@ +
+
+ All T-SHIRTS + On sale this weekend +
+
+ +
+
+ + + + +
+
+
+ +
+ +
+ +
+ © e-Shoponcontainers. All rights reserved +
+ +
+
+
+ diff --git a/src/Web/WebSPA/Client/src/modules/app.component.scss b/src/Web/WebSPA/Client/src/modules/app.component.scss new file mode 100644 index 000000000..0b48ff6e0 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/app.component.scss @@ -0,0 +1,76 @@ +@import 'src/styles/variables'; + +:host { + display: flex; + flex-direction: column; + min-height: 100%; +} + +.esh-app { + + &-header { + background: url('/assets/images/header.jpg') center -2.7rem no-repeat, linear-gradient(90deg, #5F6571 0%, #5F6571 35%, #CFC6BF 65%, #CFC6BF 100%); + background-size: 94rem, auto; + height: 13rem; + padding-top: 2.25rem; + position: relative; + transition: all $animation-speed-default; + + &--expanded { + background-position: center top; + background-size: 87rem, auto; + height: 29rem; + + .esh-app-header-promo { + opacity: 1; + } + } + } + + &-header-brand { + height: auto; + width: 92px; + } + + &-header-promo { + bottom: 3.5rem; + opacity: 0; + position: absolute; + text-align: center; + transition: all $animation-speed-default; + width: 100%; + } + + &-header-promo-title { + display: block; + color: rgba($color-brightest, .3); + font-size: 5rem; + line-height: 5rem; + word-wrap: none; + + @media screen and (min-width: $media-screen-s) { + font-size: 9rem; + line-height: 9rem; + } + } + + &-header-promo-subtitle { + display: block; + color: $color-brightest; + font-size: $font-size-xxl; + } + + &-footer { + background-color: $color-secondary-bright; + color: $color-brightest; + font-size: $font-size-m; + display: flex; + height: 7rem; + margin-top: auto; + + &-brand { + height: auto; + width: 104px; + } + } +} diff --git a/src/Web/WebSPA/Client/modules/app.component.ts b/src/Web/WebSPA/Client/src/modules/app.component.ts similarity index 89% rename from src/Web/WebSPA/Client/modules/app.component.ts rename to src/Web/WebSPA/Client/src/modules/app.component.ts index 335ca56af..d6935a41e 100644 --- a/src/Web/WebSPA/Client/modules/app.component.ts +++ b/src/Web/WebSPA/Client/src/modules/app.component.ts @@ -1,4 +1,5 @@ import { Title } from '@angular/platform-browser'; +import { Router } from '@angular/router'; import { Component, OnInit, ViewContainerRef } from '@angular/core'; import { Subscription } from 'rxjs'; @@ -21,6 +22,7 @@ export class AppComponent implements OnInit { subscription: Subscription; constructor(private titleService: Title, + public router: Router, private securityService: SecurityService, private configurationService: ConfigurationService, private signalrService: SignalrService, @@ -38,10 +40,10 @@ export class AppComponent implements OnInit { //Get configuration from server environment variables: console.log('configuration'); - this.configurationService.load(); + this.configurationService.load(); } public setTitle(newTitle: string) { - this.titleService.setTitle('eShopOnContainers'); + this.titleService.setTitle('eShopOnContainers'); } } diff --git a/src/Web/WebSPA/Client/modules/app.module.ts b/src/Web/WebSPA/Client/src/modules/app.module.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/app.module.ts rename to src/Web/WebSPA/Client/src/modules/app.module.ts diff --git a/src/Web/WebSPA/Client/modules/app.routes.ts b/src/Web/WebSPA/Client/src/modules/app.routes.ts similarity index 89% rename from src/Web/WebSPA/Client/modules/app.routes.ts rename to src/Web/WebSPA/Client/src/modules/app.routes.ts index 474d292a2..8e22eb841 100644 --- a/src/Web/WebSPA/Client/modules/app.routes.ts +++ b/src/Web/WebSPA/Client/src/modules/app.routes.ts @@ -15,4 +15,4 @@ export const routes: Routes = [ { path: 'order', component: OrdersNewComponent }, ]; -export const routing = RouterModule.forRoot(routes); +export const routing = RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' }); diff --git a/src/Web/WebSPA/Client/modules/app.service.ts b/src/Web/WebSPA/Client/src/modules/app.service.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/app.service.ts rename to src/Web/WebSPA/Client/src/modules/app.service.ts diff --git a/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.html b/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.html similarity index 54% rename from src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.html rename to src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.html index b15127a60..e0a932b2d 100644 --- a/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.html +++ b/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.html @@ -1,9 +1,9 @@ - -
- +
+
{{badge}} diff --git a/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.scss b/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.scss new file mode 100644 index 000000000..6f15d7a38 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.scss @@ -0,0 +1,39 @@ +@import 'src/styles/variables'; + +.esh-basketstatus { + cursor: pointer; + display: inline-block; + float: right; + position: relative; + transition: all $animation-speed-default; + + &.is-disabled { + opacity: .5; + pointer-events: none; + } + + &-image { + height: auto; + width: 1.5rem; + } + + &-badge { + background-color: $color-primary; + border-radius: 50%; + bottom: 0; + color: $color-brightest; + display: block; + font-size: $font-size-xs; + line-height: 1.2rem; + height: 1.2rem; + right: 0; + position: absolute; + text-align: center; + transition: all $animation-speed-fast; + width: 1.2rem; + } + + &:hover &-badge { + transform: scale(1.2) rotate(20deg); + } +} diff --git a/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.ts b/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.ts similarity index 59% rename from src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.ts rename to src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.ts index cb680e87a..e7e56d61b 100644 --- a/src/Web/WebSPA/Client/modules/basket/basket-status/basket-status.component.ts +++ b/src/Web/WebSPA/Client/src/modules/basket/basket-status/basket-status.component.ts @@ -13,33 +13,33 @@ import { ConfigurationService } from '../../shared/services/configuration.s }) export class BasketStatusComponent implements OnInit { basketItemAddedSubscription: Subscription; + basketUpdateSubscription: Subscription; authSubscription: Subscription; - basketDroppedSubscription: Subscription; badge: number = 0; - constructor(private service: BasketService, private basketEvents: BasketWrapperService, private authService: SecurityService, private configurationService: ConfigurationService) { } + constructor(private basketService: BasketService, private basketWrapperService: BasketWrapperService, private authService: SecurityService, private configurationService: ConfigurationService) { } ngOnInit() { // Subscribe to Add Basket Observable: - this.basketItemAddedSubscription = this.basketEvents.addItemToBasket$.subscribe( - item => { - this.service.addItemToBasket(item).subscribe(res => { - this.service.getBasket().subscribe(basket => { - if (basket) - this.badge = basket.items.length; - }); + this.basketItemAddedSubscription = this.basketWrapperService.addItemToBasket$.subscribe(item => { + this.basketService.addItemToBasket(item).subscribe(res => { + this.basketService.getBasket().subscribe(basket => { + if (basket) + this.badge = basket.items.length; }); }); + }); - // Subscribe to Drop Basket Observable: - this.basketDroppedSubscription = this.service.basketDroped$.subscribe(res => { - this.badge = 0; + this.basketUpdateSubscription = this.basketService.basketUpdate$.subscribe(res => { + this.basketService.getBasket().subscribe(basket => { + this.badge = basket ? basket.items.length : 0; + }); }); // Subscribe to login and logout observable this.authSubscription = this.authService.authenticationChallenge$.subscribe(res => { - this.service.getBasket().subscribe(basket => { + this.basketService.getBasket().subscribe(basket => { if (basket != null) this.badge = basket.items.length; }); @@ -47,13 +47,13 @@ export class BasketStatusComponent implements OnInit { // Init: if (this.configurationService.isReady) { - this.service.getBasket().subscribe(basket => { + this.basketService.getBasket().subscribe(basket => { if (basket != null) this.badge = basket.items.length; }); } else { this.configurationService.settingsLoaded$.subscribe(x => { - this.service.getBasket().subscribe(basket => { + this.basketService.getBasket().subscribe(basket => { if (basket != null) this.badge = basket.items.length; }); diff --git a/src/Web/WebSPA/Client/src/modules/basket/basket.component.html b/src/Web/WebSPA/Client/src/modules/basket/basket.component.html new file mode 100644 index 000000000..960509f85 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/basket/basket.component.html @@ -0,0 +1,72 @@ + diff --git a/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss b/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss new file mode 100644 index 000000000..10edb11ec --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/basket/basket.component.scss @@ -0,0 +1,121 @@ +@import 'src/styles/variables'; + +@mixin margin-left($distance) { + margin-left: $distance; +} + +.esh-basket { + + &-item { + background-color: $color-brightest; + margin-bottom: 1.5rem; + } + + &-delete { + align-items: center; + cursor: pointer; + display: flex; + height: 2rem; + justify-content: center; + position: absolute; + right: .5rem; + top: .5rem; + transition: all $animation-speed-fast; + width: 2rem; + z-index: 20; + + &:hover { + transform: scale(1.2); + } + } + + &-delete-svg { + height: auto; + width: 1.5rem; + } + + &-buttons { + width: 5rem; + } + + &-button { + align-items: center; + background: transparent; + border: 0; + cursor: pointer; + display: flex; + height: 1.5rem; + justify-content: center; + padding: 0; + transition: all $animation-speed-fast; + width: 1.5rem; + z-index: 20; + + &.is-disabled { + cursor: default; + opacity: .3; + } + } + + &-button-svg { + height: auto; + width: 1.5rem; + } + + &-thumbnail-wrapper { + background-color: #dbdede; + height: 0; + overflow: hidden; + padding-top: 100%; + position: relative; + } + + &-thumbnail { + height: 100%; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%,-50%); + width: auto; + } + + &-title { + font-size: $font-size-m; + line-height: 3rem; + padding: 0 1rem; + text-transform: uppercase; + } + + &-description { + min-height: 3rem; + padding: 0 1rem; + } + + &-quantity { + line-height: 1.5rem; + text-align: center; + width: 2rem; + } + + &-price { + color: $color-primary; + width: 4rem; + } + + &-checkout { + background-color: $color-brightest; + } + + &-checkout-title { + font-weight: $font-weight-semibold; + text-align: center; + } + + &-input { + line-height: 1rem; + width: 100%; + } +} + + + diff --git a/src/Web/WebSPA/Client/modules/basket/basket.component.ts b/src/Web/WebSPA/Client/src/modules/basket/basket.component.ts similarity index 61% rename from src/Web/WebSPA/Client/modules/basket/basket.component.ts rename to src/Web/WebSPA/Client/src/modules/basket/basket.component.ts index b0c842a3e..8528b516d 100644 --- a/src/Web/WebSPA/Client/modules/basket/basket.component.ts +++ b/src/Web/WebSPA/Client/src/modules/basket/basket.component.ts @@ -9,7 +9,7 @@ import { IBasketItem } from '../shared/models/basketItem.model'; import { BasketWrapperService } from '../shared/services/basket.wrapper.service'; @Component({ - selector: 'esh-basket', + selector: 'esh-basket .esh-basket .mb-5', styleUrls: ['./basket.component.scss'], templateUrl: './basket.component.html' }) @@ -18,22 +18,35 @@ export class BasketComponent implements OnInit { basket: IBasket; totalPrice: number = 0; - constructor(private service: BasketService, private router: Router, private basketwrapper: BasketWrapperService) { } + constructor(private basketSerive: BasketService, private router: Router, private basketWrapperService: BasketWrapperService) { } ngOnInit() { - this.service.getBasket().subscribe(basket => { + this.basketSerive.getBasket().subscribe(basket => { this.basket = basket; this.calculateTotalPrice(); }); } - itemQuantityChanged(item: IBasketItem) { + deleteItem(id: String) { + this.basket.items = this.basket.items.filter(item => item.id !== id); this.calculateTotalPrice(); - this.service.setBasket(this.basket).subscribe(x => console.log('basket updated: ' + x)); + + this.basketSerive.setBasket(this.basket).subscribe(x => + { + this.basketSerive.updateQuantity(); + console.log('basket updated: ' + x) + } + ); + } + + itemQuantityChanged(item: IBasketItem, quantity: number) { + item.quantity = quantity > 0 ? quantity : 1; + this.calculateTotalPrice(); + this.basketSerive.setBasket(this.basket).subscribe(x => console.log('basket updated: ' + x)); } update(event: any): Observable { - let setBasketObservable = this.service.setBasket(this.basket); + let setBasketObservable = this.basketSerive.setBasket(this.basket); setBasketObservable .subscribe( x => { @@ -49,7 +62,7 @@ export class BasketComponent implements OnInit { .subscribe( x => { this.errorMessages = []; - this.basketwrapper.basket = this.basket; + this.basketWrapperService.basket = this.basket; this.router.navigate(['order']); }); } diff --git a/src/Web/WebSPA/Client/modules/basket/basket.module.ts b/src/Web/WebSPA/Client/src/modules/basket/basket.module.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/basket/basket.module.ts rename to src/Web/WebSPA/Client/src/modules/basket/basket.module.ts diff --git a/src/Web/WebSPA/Client/modules/basket/basket.service.ts b/src/Web/WebSPA/Client/src/modules/basket/basket.service.ts similarity index 80% rename from src/Web/WebSPA/Client/modules/basket/basket.service.ts rename to src/Web/WebSPA/Client/src/modules/basket/basket.service.ts index a92e62bf9..b14ff3e9b 100644 --- a/src/Web/WebSPA/Client/modules/basket/basket.service.ts +++ b/src/Web/WebSPA/Client/src/modules/basket/basket.service.ts @@ -23,11 +23,11 @@ export class BasketService { items: [] }; - //observable that is fired when the basket is dropped - private basketDropedSource = new Subject(); - basketDroped$ = this.basketDropedSource.asObservable(); + //observable that is fired when item is removed from basket + private basketUpdateSource = new Subject(); + basketUpdate$ = this.basketUpdateSource.asObservable(); - constructor(private service: DataService, private authService: SecurityService, private basketEvents: BasketWrapperService, private router: Router, private configurationService: ConfigurationService, private storageService: StorageService) { + constructor(private service: DataService, private authService: SecurityService, private basketWrapperService: BasketWrapperService, private router: Router, private configurationService: ConfigurationService, private storageService: StorageService) { this.basket.items = []; // Init: @@ -49,18 +49,25 @@ export class BasketService { } } - this.basketEvents.orderCreated$.subscribe(x => { + this.basketWrapperService.orderCreated$.subscribe(x => { this.dropBasket(); }); } addItemToBasket(item): Observable { - this.basket.items.push(item); + let basketItem = this.basket.items.find(value => value.productId == item.productId); + + if (basketItem) { + basketItem.quantity++; + } else { + this.basket.items.push(item); + } + return this.setBasket(this.basket); } setBasket(basket): Observable { - let url = this.purchaseUrl + '/api/v1/basket/'; + let url = this.purchaseUrl + '/b/api/v1/basket/'; this.basket = basket; @@ -71,7 +78,7 @@ export class BasketService { let url = this.basketUrl + '/b/api/v1/basket/checkout'; return this.service.postWithId(url, basketCheckout).pipe(tap((response: any) => { - this.basketEvents.orderCreated(); + this.basketWrapperService.orderCreated(); return true; })); } @@ -107,9 +114,15 @@ export class BasketService { return basketCheckout; } + updateQuantity() { + this.basketUpdateSource.next(); + } + dropBasket() { this.basket.items = []; - this.basketDropedSource.next(); + this.setBasket(this.basket).subscribe(res => { + this.basketUpdateSource.next(); + }); } private loadData() { diff --git a/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.html b/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.html new file mode 100644 index 000000000..abed2b660 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.html @@ -0,0 +1,59 @@ +
+
+ +
+
+ + +
+
+ + +
+ +
+
+
+ +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+ {{item.name}} +
+
+ {{item.price | number:'1.2-2'}} +
+
+
+
+
+ + +
+
+ THERE ARE NO RESULTS THAT MATCH YOUR SEARCH +
+
+ diff --git a/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.scss b/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.scss new file mode 100644 index 000000000..9b06bc55d --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.scss @@ -0,0 +1,189 @@ +@import 'src/styles/variables'; + +.esh-catalog { + $banner-height: 260px; + + &-title { + position: relative; + top: $banner-height / 3.5; + } + + $filter-height: 65px; + + &-filters { + height: $filter-height; + } + + &-filters-wrapper { + padding-bottom: .5rem; + padding-top: .5rem; + } + + &-filter-wrapper { + margin-right: .5rem; + position: relative; + + &:after { + border-bottom: 1px solid $color-secondary; + border-right: 1px solid $color-secondary; + bottom: 1rem; + content: ''; + height: .5rem; + pointer-events: none; + position: absolute; + right: .9rem; + transform: rotate(45deg); + width: .5rem; + z-index: 1; + } + } + + &-filter { + appearance: none; + background-color: transparent; + border: solid 3px $color-secondary; + border-radius: 0; + cursor: pointer; + margin-right: 1rem; + min-width: 140px; + outline-color: $color-secondary; + padding-left: .5rem; + padding-right: 2rem; + + option { + appearance: none; + border: unset; + + &:hover { + background-color: $color-primary; + color: $color-brightest; + cursor: pointer; + } + + &:active { + background-color: $color-primary; + color: $color-brightest; + } + + &:focus { + background-color: $color-primary; + color: $color-brightest; + } + + &:current { + background-color: $color-primary; + color: $color-brightest; + } + + &:selected { + background-color: $color-primary; + color: $color-brightest; + } + } + } + + &-label { + display: inline-block; + font-size: $font-size-m; + margin-bottom: 0; + position: relative; + z-index: 0; + + // &:before { + // color: $color-primary; + // content: attr(data-title); + // font-size: $font-size-s; + // left: .7rem; + // top: .2rem; + // position: absolute; + // text-transform: uppercase; + // z-index: 1; + // } + } + + &-items { + margin-top: 1rem; + } + + &-item { + cursor: pointer; + margin-bottom: 1.5rem; + width: 100%; + + &:hover { + background-color: $color-brightest; + + .esh-catalog-thumbnail-icon { + opacity: 1; + } + } + + &.is-disabled { + background-color: unset; + cursor: default; + + .esh-catalog-thumbnail-icon { + display: none !important; + } + } + } + + &-thumbnail-wrapper { + background-color: #dbdede; + height: 0; + overflow: hidden; + padding-top: 100%; + position: relative; + } + + &-thumbnail-icon { + background-color: $color-primary; + border-radius: 50%; + height: 3.5rem; + left: 50%; + opacity: 0; + position: absolute; + top: 50%; + transform: translate(-50%,-50%); + width: 3.5rem; + z-index: 20; + transition: all $animation-speed-default; + } + + &-thumbnail-icon-svg { + height: auto; + width: 1.5rem; + } + + &-thumbnail { + height: 100%; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%,-50%); + width: auto; + z-index: 10; + } + + &-details { + height: 4rem; + } + + &-name { + font-size: $font-size-m; + text-transform: uppercase; + } + + &-price { + color: $color-primary; + font-size: $font-size-m; + + &::before { + content: '$'; + } + } + + &-alert { + margin-top: 10px; + } +} diff --git a/src/Web/WebSPA/Client/modules/catalog/catalog.component.ts b/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.ts similarity index 94% rename from src/Web/WebSPA/Client/modules/catalog/catalog.component.ts rename to src/Web/WebSPA/Client/src/modules/catalog/catalog.component.ts index c4538b393..59e85e8c9 100644 --- a/src/Web/WebSPA/Client/modules/catalog/catalog.component.ts +++ b/src/Web/WebSPA/Client/src/modules/catalog/catalog.component.ts @@ -13,7 +13,7 @@ import { BasketWrapperService} from '../shared/services/basket.wrapper.service' import { SecurityService } from '../shared/services/security.service'; @Component({ - selector: 'esh-catalog .esh-catalog', + selector: 'esh-catalog .esh-catalog .mb-5', styleUrls: ['./catalog.component.scss'], templateUrl: './catalog.component.html' }) @@ -50,7 +50,7 @@ export class CatalogComponent implements OnInit { loadData() { this.getBrands(); - this.getCatalog(10, 0); + this.getCatalog(12, 0); this.getTypes(); } @@ -59,6 +59,7 @@ export class CatalogComponent implements OnInit { this.brandSelected = this.brandSelected && this.brandSelected.toString() != "null" ? this.brandSelected : null; this.typeSelected = this.typeSelected && this.typeSelected.toString() != "null" ? this.typeSelected : null; + this.paginationInfo.actualPage = 0; this.getCatalog(this.paginationInfo.itemsPage, this.paginationInfo.actualPage, this.brandSelected, this.typeSelected); } @@ -80,12 +81,14 @@ export class CatalogComponent implements OnInit { } addToCart(item: ICatalogItem) { + if (!this.authenticated) { + return; + } this.basketService.addItemToBasket(item); } getCatalog(pageSize: number, pageIndex: number, brand?: number, type?: number) { this.errorReceived = false; - this.service.getCatalog(pageIndex, pageSize, brand, type) .pipe(catchError((err) => this.handleError(err))) .subscribe(catalog => { @@ -95,7 +98,7 @@ export class CatalogComponent implements OnInit { itemsPage : catalog.pageSize, totalItems : catalog.count, totalPages: Math.ceil(catalog.count / catalog.pageSize), - items: catalog.data.length + items: catalog.pageSize }; }); } diff --git a/src/Web/WebSPA/Client/modules/catalog/catalog.module.ts b/src/Web/WebSPA/Client/src/modules/catalog/catalog.module.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/catalog/catalog.module.ts rename to src/Web/WebSPA/Client/src/modules/catalog/catalog.module.ts diff --git a/src/Web/WebSPA/Client/modules/catalog/catalog.service.ts b/src/Web/WebSPA/Client/src/modules/catalog/catalog.service.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/catalog/catalog.service.ts rename to src/Web/WebSPA/Client/src/modules/catalog/catalog.service.ts diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html new file mode 100644 index 000000000..e0ea4f722 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.html @@ -0,0 +1,47 @@ +
+
+

[ Order List Detail ]

+
+
+
Order number
+
Date
+
Total
+
Status
+
+ +
+
{{order.ordernumber}}
+
{{order.date | date:'short'}}
+
$ {{order.total}}
+
{{order.status}}
+
+ +

Shipping address

+
{{order.street}} {{order.city}} {{order.country}}
+ +
+
+
+ +
+
+
+
{{item.productname}}
+
$ {{item.unitprice | number:'.2-2'}}
+
{{item.units}}
+
${{(item.units * item.unitprice) | number:'.2-2'}}
+
+
+ +
+
Total
+
${{order.total | number:'.2-2'}}
+
+ + +
+
+
diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.scss b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.scss new file mode 100644 index 000000000..74daaa91e --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.scss @@ -0,0 +1,45 @@ +@import 'src/styles/variables'; + +.esh-orders_detail { + + &-titles { + color: $color-secondary-bright; + font-size: $font-size-l; + font-weight: $font-weight-semilight; + margin-bottom: 1.5rem; + text-transform: uppercase; + } + + &-title { + color: $color-secondary-bright; + font-size: $font-size-l; + font-weight: $font-weight-semilight; + text-transform: uppercase; + } + + &-items { + font-size: $font-size-m; + font-weight: $font-weight-normal; + } + + &-thumbnail-container { + width: 10rem; + } + + &-thumbnail-wrapper { + background-color: #dbdede; + height: 0; + overflow: hidden; + padding-top: 100%; + position: relative; + } + + &-thumbnail { + height: 100%; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%,-50%); + width: auto; + } +} diff --git a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.ts b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.ts similarity index 94% rename from src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.ts rename to src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.ts index c9c5c79c0..1ccae3e24 100644 --- a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.ts +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-detail/orders-detail.component.ts @@ -4,7 +4,7 @@ import { IOrderDetail } from '../../shared/models/order-detail.model'; import { ActivatedRoute } from '@angular/router'; @Component({ - selector: 'esh-orders_detail', + selector: 'esh-orders_detail .esh-orders_detail .mb-5', styleUrls: ['./orders-detail.component.scss'], templateUrl: './orders-detail.component.html' }) diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html new file mode 100644 index 000000000..18311597a --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.html @@ -0,0 +1,99 @@ +
+

[ Checkout ]

+ +
+
+

Shipping Address

+
+
+
+ + +
Required field.
+
+
+
+
+ + +
Required field.
+
+
+
+
+ + +
Required field.
+
+
+
+
+ + +
Required field.
+
+
+
+

Payment method

+
+
+
+ + +
Required field.
+
+
+
+
+ + +
Required field.
+
+
+
+
+ + +
Required field.
+
+
+
+
+ + +
Required field.
+
+
+
+ +

Order details

+
+
+
+ +
+
+
+
{{item.productname}}
+
$ {{item.unitprice | number:'.2-2'}}
+
{{item.units}}
+
$ {{(item.units * item.unitprice) | number:'.2-2'}}
+
+
+ +
+
Total
+
${{ order.total | number:'.2-2'}}
+
+ +
+ Back to basket + + +
+
+
+
\ No newline at end of file diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss new file mode 100644 index 000000000..25bdc60af --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.scss @@ -0,0 +1,39 @@ +@import 'src/styles/variables'; + +.esh-orders_new { + + &-titles { + padding-bottom: 1rem; + padding-top: 2rem; + } + + &-item { + font-size: $font-size-m; + font-weight: $font-weight-semilight; + } + + &-thumbnail-container { + width: 10rem; + } + + &-thumbnail-wrapper { + background-color: #dbdede; + height: 0; + overflow: hidden; + padding-top: 100%; + position: relative; + } + + &-thumbnail { + height: 100%; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%,-50%); + width: auto; + } + + &-buttons { + margin-top: 5rem; + } +} diff --git a/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.ts b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts similarity index 97% rename from src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.ts rename to src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts index d983cf171..ff84b7638 100644 --- a/src/Web/WebSPA/Client/modules/orders/orders-new/orders-new.component.ts +++ b/src/Web/WebSPA/Client/src/modules/orders/orders-new/orders-new.component.ts @@ -11,7 +11,7 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Router } from '@angular/router'; @Component({ - selector: 'esh-orders_new', + selector: 'esh-orders_new .esh-orders_new .mb-5', styleUrls: ['./orders-new.component.scss'], templateUrl: './orders-new.component.html' }) @@ -39,7 +39,7 @@ export class OrdersNewComponent implements OnInit { ngOnInit() { } - submitForm(value: any) { + submitForm(value: any) { this.order.street = this.newOrderForm.controls['street'].value; this.order.city = this.newOrderForm.controls['city'].value; this.order.state = this.newOrderForm.controls['state'].value; diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders.component.html b/src/Web/WebSPA/Client/src/modules/orders/orders.component.html new file mode 100644 index 000000000..a24f22fd7 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/orders/orders.component.html @@ -0,0 +1,37 @@ +
+
+

[ Order List ]

+ + +
+
+
+
Date
+
Total
+
Status
+
+
+
+ +
+
{{order.ordernumber}}
+
{{order.date | date:'short'}}
+
${{order.total}}
+
{{order.status}}
+
+ Cancel +
+
+ Details +
+
+ + +
+
+
diff --git a/src/Web/WebSPA/Client/src/modules/orders/orders.component.scss b/src/Web/WebSPA/Client/src/modules/orders/orders.component.scss new file mode 100644 index 000000000..57ccbf5e0 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/orders/orders.component.scss @@ -0,0 +1,39 @@ +@import 'src/styles/variables'; + +.esh-orders { + + &-wrapper { + background-color: $color-brightest; + padding-bottom: 4rem; + padding-top: 4rem; + } + + &-titles { + color: $color-secondary-bright; + font-size: $font-size-l; + font-weight: $font-weight-semilight; + margin-bottom: 1rem; + padding-left: 5rem; + text-transform: uppercase; + } + + &-item { + $height: 6rem; + font-size: $font-size-m; + font-weight: $font-weight-normal; + height: $height; + line-height: $height; + padding-left: 5rem; + position: relative; + } + + &-link { + color: $color-primary; + text-decoration: none; + transition: color $animation-speed-default; + + &:hover { + color: $color-secondary; + } + } +} diff --git a/src/Web/WebSPA/Client/modules/orders/orders.component.ts b/src/Web/WebSPA/Client/src/modules/orders/orders.component.ts similarity index 83% rename from src/Web/WebSPA/Client/modules/orders/orders.component.ts rename to src/Web/WebSPA/Client/src/modules/orders/orders.component.ts index 4d881c431..25882d2c3 100644 --- a/src/Web/WebSPA/Client/modules/orders/orders.component.ts +++ b/src/Web/WebSPA/Client/src/modules/orders/orders.component.ts @@ -7,7 +7,7 @@ import { catchError } from 'rxjs/operators'; import { SignalrService } from '../shared/services/signalr.service'; @Component({ - selector: 'esh-orders', + selector: 'esh-orders .esh-orders .mb-5', styleUrls: ['./orders.component.scss'], templateUrl: './orders.component.html' }) @@ -44,6 +44,15 @@ export class OrdersComponent implements OnInit { }); } + cancelOrder(orderNumber) { + this.errorReceived = false; + this.service.cancelOrder(orderNumber) + .pipe(catchError((err) => this.handleError(err))) + .subscribe(() => { + console.log('order canceled: ' + orderNumber); + }); + } + private handleError(error: any) { this.errorReceived = true; return Observable.throw(error); diff --git a/src/Web/WebSPA/Client/modules/orders/orders.module.ts b/src/Web/WebSPA/Client/src/modules/orders/orders.module.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/orders/orders.module.ts rename to src/Web/WebSPA/Client/src/modules/orders/orders.module.ts diff --git a/src/Web/WebSPA/Client/modules/orders/orders.service.ts b/src/Web/WebSPA/Client/src/modules/orders/orders.service.ts similarity index 90% rename from src/Web/WebSPA/Client/modules/orders/orders.service.ts rename to src/Web/WebSPA/Client/src/modules/orders/orders.service.ts index bd60f5b99..e81d6da64 100644 --- a/src/Web/WebSPA/Client/modules/orders/orders.service.ts +++ b/src/Web/WebSPA/Client/src/modules/orders/orders.service.ts @@ -9,7 +9,7 @@ import { ConfigurationService } from '../shared/services/configuration.service'; import { BasketWrapperService } from '../shared/services/basket.wrapper.service'; import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; +import { tap, map } from 'rxjs/operators'; @Injectable() export class OrdersService { @@ -31,6 +31,15 @@ export class OrdersService { })); } + cancelOrder(orderNumber: number): Observable { + let url = this.ordersUrl + '/o/api/v1/orders/cancel'; + let data = { OrderNumber: orderNumber }; + + return this.service.putWithId(url, data).pipe(tap(() => { + return; + })); + } + getOrder(id: number): Observable { let url = this.ordersUrl + '/o/api/v1/orders/' + id; diff --git a/src/Web/WebSPA/Client/modules/shared/components/header/header.html b/src/Web/WebSPA/Client/src/modules/shared/components/header/header.html similarity index 100% rename from src/Web/WebSPA/Client/modules/shared/components/header/header.html rename to src/Web/WebSPA/Client/src/modules/shared/components/header/header.html diff --git a/src/Web/WebSPA/Client/modules/shared/components/header/header.scss b/src/Web/WebSPA/Client/src/modules/shared/components/header/header.scss similarity index 66% rename from src/Web/WebSPA/Client/modules/shared/components/header/header.scss rename to src/Web/WebSPA/Client/src/modules/shared/components/header/header.scss index 98d455ccf..ace3220a5 100644 --- a/src/Web/WebSPA/Client/modules/shared/components/header/header.scss +++ b/src/Web/WebSPA/Client/src/modules/shared/components/header/header.scss @@ -1,20 +1,20 @@ -@import '../../../variables'; +@import 'src/styles/variables'; .esh-header { $header-height: 4rem; - background-color: $color-brand; + background-color: $color-primary; height: $header-height; &-back { - color: rgba($color-foreground-brighter, .5); + color: rgba($color-brightest, .5); line-height: $header-height; text-decoration: none; text-transform: uppercase; transition: color $animation-speed-default; &:hover { - color: $color-foreground-brighter; + color: $color-brightest; transition: color $animation-speed-default; } } diff --git a/src/Web/WebSPA/Client/modules/shared/components/header/header.ts b/src/Web/WebSPA/Client/src/modules/shared/components/header/header.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/shared/components/header/header.ts rename to src/Web/WebSPA/Client/src/modules/shared/components/header/header.ts diff --git a/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.html b/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.html new file mode 100644 index 000000000..c128e4ae5 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.html @@ -0,0 +1,32 @@ +
+
+
+ +
LOGIN + +
+
+
+ +
+ +
{{userName}}
+ +
+ +
+ +
+
My orders
+
+ +
+
Log Out
+
+
+
diff --git a/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.scss b/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.scss new file mode 100644 index 000000000..1df351db7 --- /dev/null +++ b/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.scss @@ -0,0 +1,52 @@ +@import 'src/styles/variables'; + +.esh-identity { + position: relative; + + &-section { + width: 100%; + } + + &-name { + font-size: $font-size-s; + display: inline-block; + + &--upper { + text-transform: uppercase; + } + } + + &-image { + height: auto; + width: 1.5rem; + } + + &-drop { + background: $color-brightest; + height: 0; + min-width: 10rem; + overflow: hidden; + position: absolute; + right: 0; + top: 2.5rem; + transition: height $animation-speed-default; + } + + &:hover &-drop { + height: 5rem; + } + + &-item { + color: $color-primary; + cursor: pointer; + font-size: $font-size-s; + line-height: 2.5rem; + padding: 0 1rem; + transition: all $animation-speed-default; + + &:hover { + background-color: $color-secondary-brightest; + color: $color-secondary; + } + } +} diff --git a/src/Web/WebSPA/Client/modules/shared/components/identity/identity.ts b/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.ts similarity index 94% rename from src/Web/WebSPA/Client/modules/shared/components/identity/identity.ts rename to src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.ts index 83b166b36..7797341e9 100644 --- a/src/Web/WebSPA/Client/modules/shared/components/identity/identity.ts +++ b/src/Web/WebSPA/Client/src/modules/shared/components/identity/identity.ts @@ -29,7 +29,7 @@ export class Identity implements OnInit { this.service.AuthorizedCallback(); } - console.log('identity component, checking authorized ' + this.service.IsAuthorized); + console.log('identity component, checking authorized' + this.service.IsAuthorized); this.authenticated = this.service.IsAuthorized; if (this.authenticated) { diff --git a/src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.html b/src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.html similarity index 100% rename from src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.html rename to src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.html diff --git a/src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.scss b/src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.scss similarity index 100% rename from src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.scss rename to src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.scss diff --git a/src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.spec.ts b/src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.spec.ts similarity index 82% rename from src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.spec.ts rename to src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.spec.ts index 72384fb48..f3781634c 100644 --- a/src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.spec.ts +++ b/src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.spec.ts @@ -1,6 +1,6 @@ /* tslint:disable:no-unused-variable */ -import { TestBed, async } from '@angular/core/testing'; +import { TestBed, waitForAsync } from '@angular/core/testing'; import { PageNotFoundComponent } from './page-not-found.component'; describe('Component: PageNotFound', () => { diff --git a/src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.ts b/src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.ts similarity index 100% rename from src/Web/WebSPA/Client/modules/shared/components/page-not-found/page-not-found.component.ts rename to src/Web/WebSPA/Client/src/modules/shared/components/page-not-found/page-not-found.component.ts diff --git a/src/Web/WebSPA/Client/modules/shared/components/pager/pager.html b/src/Web/WebSPA/Client/src/modules/shared/components/pager/pager.html similarity index 96% rename from src/Web/WebSPA/Client/modules/shared/components/pager/pager.html rename to src/Web/WebSPA/Client/src/modules/shared/components/pager/pager.html index 68996a928..567540c63 100644 --- a/src/Web/WebSPA/Client/modules/shared/components/pager/pager.html +++ b/src/Web/WebSPA/Client/src/modules/shared/components/pager/pager.html @@ -1,7 +1,7 @@
-